Servos with higher refreshrate

This forum is dedicated to software development related to MultiWii.
It is not the right place to submit a setup problem.
Software download
Post Reply
ronco
Posts: 317
Joined: Thu Aug 18, 2011 2:58 pm

Servos with higher refreshrate

Post by ronco »

Hi,

i did some tests with our soft PWM servo code. i would like to have the possibility to run the servos with more then 50Hz .. because for what i know the most digital servos works well with up to 300Hz.

so i changed the servo ISR to work in a chain order. it works well as it is .. and it cleans also the compiled code inside of it. but to have the flexibility of the used "from - to servo selection" which i like! i had to re sort them to have a clean serie (servo 1-4 instead of 1-2 and 4-5). and this is the part im not happy with :(.. to do it with the compiler i ended up with a very big #if block..

i hope that there are smarter ways that i dont know ;)

some measurements (with SERVO_FAST_PWM)
- 1 servo = ~280Hz (the frequency changes with the servos position .. so it is between 320-240Hz..)
- 2 servos = ~250Hz
- 3 servos = ~216Hz
- 4 servos = ~163Hz
- 6 servos = ~110Hz
- 8 servos = ~ 82Hz

without SERVO_FAST_PWM it varies between 49-60Hz



my test code..

the #if block in def.h (to add under the servo from-to defines)

Code: Select all

/**********************   Sort the Servos for the moust ideal SW PWM     ************************/
// this define block sorts the above slected servos to be in a simple order from 1 - (count of total servos)
// its pretty fat but its the best way i found to get less compiled code and max speed in the ISR without loosing its flexibility
#if (PRI_SERVO_FROM == 1) || (SEC_SERVO_FROM == 1)
  #define LAST_LOW SERVO_1_PIN_LOW
  #define SERVO_1_HIGH SERVO_1_PIN_HIGH
  #define SERVO_1_LOW SERVO_1_PIN_LOW
  #define SERVO_1_ARR_POS  0
#endif
#if (PRI_SERVO_FROM <= 2 && PRI_SERVO_TO >= 2) || (SEC_SERVO_FROM <= 2 && SEC_SERVO_TO >= 2)
  #undef LAST_LOW
  #define LAST_LOW SERVO_2_PIN_LOW
  #if !defined(SERVO_1_HIGH)
    #define SERVO_1_HIGH SERVO_2_PIN_HIGH
    #define SERVO_1_LOW SERVO_2_PIN_LOW 
    #define SERVO_1_ARR_POS 1
  #else
    #define SERVO_2_HIGH SERVO_2_PIN_HIGH
    #define SERVO_2_LOW SERVO_2_PIN_LOW   
    #define SERVO_2_ARR_POS 1
  #endif
#endif
#if (PRI_SERVO_FROM <= 3 && PRI_SERVO_TO >= 3) || (SEC_SERVO_FROM <= 3 && SEC_SERVO_TO >= 3)
  #undef LAST_LOW
  #define LAST_LOW SERVO_3_PIN_LOW
  #if !defined(SERVO_1_HIGH)
    #define SERVO_1_HIGH SERVO_3_PIN_HIGH
    #define SERVO_1_LOW SERVO_3_PIN_LOW
    #define SERVO_1_ARR_POS 2
  #elif !defined(SERVO_2_HIGH)
    #define SERVO_2_HIGH SERVO_3_PIN_HIGH
    #define SERVO_2_LOW SERVO_3_PIN_LOW
    #define SERVO_2_ARR_POS 2
  #else
    #define SERVO_3_HIGH SERVO_3_PIN_HIGH
    #define SERVO_3_LOW SERVO_3_PIN_LOW 
    #define SERVO_3_ARR_POS 2   
  #endif
#endif
#if (PRI_SERVO_FROM <= 4 && PRI_SERVO_TO >= 4) || (SEC_SERVO_FROM <= 4 && SEC_SERVO_TO >= 4)
  #undef LAST_LOW
  #define LAST_LOW SERVO_4_PIN_LOW
  #if !defined(SERVO_1_HIGH)
    #define SERVO_1_HIGH SERVO_4_PIN_HIGH
    #define SERVO_1_LOW SERVO_4_PIN_LOW
    #define SERVO_1_ARR_POS 3 
  #elif !defined(SERVO_2_HIGH)
    #define SERVO_2_HIGH SERVO_4_PIN_HIGH
    #define SERVO_2_LOW SERVO_4_PIN_LOW
    #define SERVO_2_ARR_POS 3
  #elif !defined(SERVO_3_HIGH)
    #define SERVO_3_HIGH SERVO_4_PIN_HIGH
    #define SERVO_3_LOW SERVO_4_PIN_LOW
    #define SERVO_3_ARR_POS 3   
  #else
    #define SERVO_4_HIGH SERVO_4_PIN_HIGH
    #define SERVO_4_LOW SERVO_4_PIN_LOW
    #define SERVO_4_ARR_POS 3     
  #endif
#endif
#if (PRI_SERVO_FROM <= 5 && PRI_SERVO_TO >= 5) || (SEC_SERVO_FROM <= 5 && SEC_SERVO_TO >= 5)
  #undef LAST_LOW
  #define LAST_LOW SERVO_5_PIN_LOW
  #if !defined(SERVO_1_HIGH)
    #define SERVO_1_HIGH SERVO_5_PIN_HIGH
    #define SERVO_1_LOW SERVO_5_PIN_LOW
    #define SERVO_1_ARR_POS 4   
  #elif !defined(SERVO_2_HIGH)
    #define SERVO_2_HIGH SERVO_5_PIN_HIGH
    #define SERVO_2_LOW SERVO_5_PIN_LOW
    #define SERVO_2_ARR_POS 4 
  #elif !defined(SERVO_3_HIGH)
    #define SERVO_3_HIGH SERVO_5_PIN_HIGH
    #define SERVO_3_LOW SERVO_5_PIN_LOW
    #define SERVO_3_ARR_POS 4   
  #elif !defined(SERVO_4_HIGH)
    #define SERVO_4_HIGH SERVO_5_PIN_HIGH
    #define SERVO_4_LOW SERVO_5_PIN_LOW
    #define SERVO_4_ARR_POS 4   
  #else
    #define SERVO_5_HIGH SERVO_5_PIN_HIGH
    #define SERVO_5_LOW SERVO_5_PIN_LOW
    #define SERVO_5_ARR_POS 4     
  #endif
#endif
#if (PRI_SERVO_FROM <= 6 && PRI_SERVO_TO >= 6) || (SEC_SERVO_FROM <= 6 && SEC_SERVO_TO >= 6)
  #undef LAST_LOW
  #define LAST_LOW SERVO_6_PIN_LOW
  #if !defined(SERVO_1_HIGH)
    #define SERVO_1_HIGH SERVO_6_PIN_HIGH
    #define SERVO_1_LOW SERVO_6_PIN_LOW
    #define SERVO_1_ARR_POS 5
  #elif !defined(SERVO_2_HIGH)
    #define SERVO_2_HIGH SERVO_6_PIN_HIGH
    #define SERVO_2_LOW SERVO_6_PIN_LOW
    #define SERVO_2_ARR_POS 5
  #elif !defined(SERVO_3_HIGH)
    #define SERVO_3_HIGH SERVO_6_PIN_HIGH
    #define SERVO_3_LOW SERVO_6_PIN_LOW
    #define SERVO_3_ARR_POS 5   
  #elif !defined(SERVO_4_HIGH)
    #define SERVO_4_HIGH SERVO_6_PIN_HIGH
    #define SERVO_4_LOW SERVO_6_PIN_LOW
    #define SERVO_4_ARR_POS 5 
  #elif !defined(SERVO_5_HIGH)
    #define SERVO_5_HIGH SERVO_6_PIN_HIGH
    #define SERVO_5_LOW SERVO_6_PIN_LOW
    #define SERVO_5_ARR_POS 5 
  #else
    #define SERVO_6_HIGH SERVO_6_PIN_HIGH
    #define SERVO_6_LOW SERVO_6_PIN_LOW 
    #define SERVO_6_ARR_POS 5   
  #endif
#endif
#if (PRI_SERVO_FROM <= 7 && PRI_SERVO_TO >= 7) || (SEC_SERVO_FROM <= 7 && SEC_SERVO_TO >= 7)
  #undef LAST_LOW
  #define LAST_LOW SERVO_7_PIN_LOW
  #if !defined(SERVO_1_HIGH)
    #define SERVO_1_HIGH SERVO_7_PIN_HIGH
    #define SERVO_1_LOW SERVO_7_PIN_LOW
    #define SERVO_1_ARR_POS 6
  #elif !defined(SERVO_2_HIGH)
    #define SERVO_2_HIGH SERVO_7_PIN_HIGH
    #define SERVO_2_LOW SERVO_7_PIN_LOW
    #define SERVO_2_ARR_POS 6
  #elif !defined(SERVO_3_HIGH)
    #define SERVO_3_HIGH SERVO_7_PIN_HIGH
    #define SERVO_3_LOW SERVO_7_PIN_LOW
    #define SERVO_3_ARR_POS 6   
  #elif !defined(SERVO_4_HIGH)
    #define SERVO_4_HIGH SERVO_7_PIN_HIGH
    #define SERVO_4_LOW SERVO_7_PIN_LOW
    #define SERVO_4_ARR_POS 6 
  #elif !defined(SERVO_5_HIGH)
    #define SERVO_5_HIGH SERVO_7_PIN_HIGH
    #define SERVO_5_LOW SERVO_7_PIN_LOW
    #define SERVO_5_ARR_POS 6 
  #elif !defined(SERVO_6_HIGH)
    #define SERVO_6_HIGH SERVO_7_PIN_HIGH
    #define SERVO_6_LOW SERVO_7_PIN_LOW
    #define SERVO_6_ARR_POS 6 
  #else
    #define SERVO_7_HIGH SERVO_7_PIN_HIGH
    #define SERVO_7_LOW SERVO_7_PIN_LOW 
    #define SERVO_7_ARR_POS 6   
  #endif
#endif
#if (PRI_SERVO_FROM <= 8 && PRI_SERVO_TO >= 8) || (SEC_SERVO_FROM <= 8 && SEC_SERVO_TO >= 8)
  #undef LAST_LOW
  #define LAST_LOW SERVO_8_PIN_LOW
  #if !defined(SERVO_1_HIGH)
    #define SERVO_1_HIGH SERVO_8_PIN_HIGH
    #define SERVO_1_LOW SERVO_8_PIN_LOW
    #define SERVO_1_ARR_POS 7
  #elif !defined(SERVO_2_HIGH)
    #define SERVO_2_HIGH SERVO_8_PIN_HIGH
    #define SERVO_2_LOW SERVO_8_PIN_LOW
    #define SERVO_2_ARR_POS 7
  #elif !defined(SERVO_3_HIGH)
    #define SERVO_3_HIGH SERVO_8_PIN_HIGH
    #define SERVO_3_LOW SERVO_8_PIN_LOW
    #define SERVO_3_ARR_POS 7 
  #elif !defined(SERVO_4_HIGH)
    #define SERVO_4_HIGH SERVO_8_PIN_HIGH
    #define SERVO_4_LOW SERVO_8_PIN_LOW
    #define SERVO_4_ARR_POS 7 
  #elif !defined(SERVO_5_HIGH)
    #define SERVO_5_HIGH SERVO_8_PIN_HIGH
    #define SERVO_5_LOW SERVO_8_PIN_LOW
    #define SERVO_5_ARR_POS 7 
  #elif !defined(SERVO_6_HIGH)
    #define SERVO_6_HIGH SERVO_8_PIN_HIGH
    #define SERVO_6_LOW SERVO_8_PIN_LOW
    #define SERVO_6_ARR_POS 7
  #elif !defined(SERVO_7_HIGH)
    #define SERVO_7_HIGH SERVO_8_PIN_HIGH
    #define SERVO_7_LOW SERVO_8_PIN_LOW
    #define SERVO_7_ARR_POS 7 
  #else
    #define SERVO_8_HIGH SERVO_8_PIN_HIGH
    #define SERVO_8_LOW SERVO_8_PIN_LOW 
    #define SERVO_8_ARR_POS 7   
  #endif
#endif



in Output.pde

Code: Select all


#define SERVO_FAST_PWM // to activate it

// for servo 2-8
// its almost the same as for servo 1
#define SERVO_PULSE(PIN_HIGH,ACT_STATE,SERVO_NUM,LAST_PIN_LOW) \
  }else if(state == ACT_STATE){                                \
    LAST_PIN_LOW;                                              \
    PIN_HIGH;                                                  \
    SERVO_CHANNEL+=SERVO_1K_US;                                \
    state++;                                                   \
  }else if(state == ACT_STATE+1){                              \
    SERVO_CHANNEL+=atomicServo[SERVO_NUM];                     \
    state++;                                                   \

ISR(SERVO_ISR) {
  static uint8_t state = 0; // indicates the current state of the chain
  if(state == 0){
    SERVO_1_HIGH; // set servo 1's pin high
    SERVO_CHANNEL+=SERVO_1K_US; // wait 1000us
    state++; // count up the state
  }else if(state==1){
    SERVO_CHANNEL+=atomicServo[SERVO_1_ARR_POS]; // load the servo's value (0-1000us)
    state++; // count up the state
  #if defined(SERVO_2_HIGH)
    SERVO_PULSE(SERVO_2_HIGH,2,SERVO_2_ARR_POS,SERVO_1_LOW); // the same here
  #endif
  #if defined(SERVO_3_HIGH)
    SERVO_PULSE(SERVO_3_HIGH,4,SERVO_3_ARR_POS,SERVO_2_LOW);
  #endif
  #if defined(SERVO_4_HIGH)
    SERVO_PULSE(SERVO_4_HIGH,6,SERVO_4_ARR_POS,SERVO_3_LOW);
  #endif
  #if defined(SERVO_5_HIGH)
    SERVO_PULSE(SERVO_5_HIGH,8,SERVO_5_ARR_POS,SERVO_4_LOW);
  #endif
  #if defined(SERVO_6_HIGH)
    SERVO_PULSE(SERVO_6_HIGH,10,SERVO_6_ARR_POS,SERVO_5_LOW);
  #endif
  #if defined(SERVO_7_HIGH)
    SERVO_PULSE(SERVO_7_HIGH,12,SERVO_7_ARR_POS,SERVO_6_LOW);
  #endif
  #if defined(SERVO_8_HIGH)
    SERVO_PULSE(SERVO_8_HIGH,14,SERVO_8_ARR_POS,SERVO_7_LOW);
  #endif
  }else{
    LAST_LOW;
    #if defined(SERVO_FAST_PWM)
      #if defined(SERVO_3_HIGH)  // if there are 3 or more servos we dont need to slow it down
        SERVO_CHANNEL+=(SERVO_1K_US>>3); // 0 would be better but it cause bad jitter
        state=0;
      #else // if there are less then 3 servos we need to slow it to not go over 300Hz (the highest working refresh rate for the digital servos for what i know..)
        SERVO_CHANNEL+=SERVO_1K_US;
        if(state<4){
          state+=2;
        }else{
          state=0;
        }
      #endif
    #else // to have ~ 50Hz for all servos
      SERVO_CHANNEL+=SERVO_1K_US;
      if(state<30){
        state+=2;
      }else{
        state=0;
      }     
    #endif
  }
}


regards

Felix

katana
Posts: 48
Joined: Thu Oct 20, 2011 6:49 pm

Re: Servos with higher refreshrate

Post by katana »

Hi felix!

I am studying a way to make my gimbal as smooth as possible.
I use powerful, digital and fast servo, transfer of the motion through pulleys and external pots.

After many tests I believe that the weak point is the 50Hz of gimbal output...

Is it possible with your modification to pilot the 2 servo up to 300hz?

Thanks in advance

ronco
Posts: 317
Joined: Thu Aug 18, 2011 2:58 pm

Re: Servos with higher refreshrate

Post by ronco »

Hi katana,

katana wrote:Is it possible with your modification to pilot the 2 servo up to 300hz?


yes it is what this code does :)
you can use the actual shared trunk version. i added this code there.

you just need to change:

Code: Select all

/***********************         Servo Refreshrates            ***********************/
/* Default 50Hz Servo refresh rate*/
#define SERVO_RFR_50HZ

/* up to 160Hz servo refreshrate .. works with the most analog servos*/
//#define SERVO_RFR_160HZ

/* up to 300Hz refreshrate it is as fast as possible (100-300Hz depending on the cound of used servos and the servos state).
   for use with digital servos
   dont use it with analog servos! thay may get damage. (some will work but be careful)*/
//#define SERVO_RFR_300HZ

to

Code: Select all

/***********************         Servo Refreshrates            ***********************/
/* Default 50Hz Servo refresh rate*/
//#define SERVO_RFR_50HZ

/* up to 160Hz servo refreshrate .. works with the most analog servos*/
//#define SERVO_RFR_160HZ

/* up to 300Hz refreshrate it is as fast as possible (100-300Hz depending on the cound of used servos and the servos state).
   for use with digital servos
   dont use it with analog servos! thay may get damage. (some will work but be careful)*/
#define SERVO_RFR_300HZ


regards

felix

katana
Posts: 48
Joined: Thu Oct 20, 2011 6:49 pm

Re: Servos with higher refreshrate

Post by katana »

Thanks Felix!
I download every file i found here: http://code.google.com/p/multiwii/sourc ... Wii_shared
then i open the config.h and modify how you showed me. upload, ok.
But it's impossible to comunicate with MultiWiiConf_2_0.exe the version is it is not recognized :(
Where I can download a usable version of MultiWiiConf_???_0.exe

Or even better it is possible to modify multiwii 2. 0 (the stable version) with only this mod ?

I think It's to add some line in config.h

Code: Select all

/***********************         Servo Refreshrates            ***********************/
/* Default 50Hz Servo refresh rate*/
//#define SERVO_RFR_50HZ

/* up to 160Hz servo refreshrate .. works with the most analog servos*/
//#define SERVO_RFR_160HZ

/* up to 300Hz refreshrate it is as fast as possible (100-300Hz depending on the cound of used servos and the servos state).
   for use with digital servos
   dont use it with analog servos! thay may get damage. (some will work but be careful)*/
#define SERVO_RFR_300HZ


and replace other in Output.ino... but personally I am not very expert

regards

katana

ronco
Posts: 317
Joined: Thu Aug 18, 2011 2:58 pm

Re: Servos with higher refreshrate

Post by ronco »

hi,

here is a compiled GUI for windows. -> http://www.2shared.com/file/WhSsT1hB/MWC_conf.html

its not that simple to mix the files of the dev and the 2.0

regards Felix

copterrichie
Posts: 2261
Joined: Sat Feb 19, 2011 8:30 pm

Re: Servos with higher refreshrate

Post by copterrichie »

This just be the answer to a prayer for my bicopters. I will give it a test and report back.

katana
Posts: 48
Joined: Thu Oct 20, 2011 6:49 pm

Re: Servos with higher refreshrate

Post by katana »

Thanks Felix!!!!
It promises really well this mod, I have tested by hand moving and rolling, it is another gimbal! (i use 2 hyperion Atlas Servo)
I cannot test it in flight seen that it is a very much revised version, I do not trust.

This modification must find space in multiwii 2. 1 !

I want to test in flight as soon as possible, I want to try to implement the mod in multiwii 2.0 (stable )

ronco
Posts: 317
Joined: Thu Aug 18, 2011 2:58 pm

Re: Servos with higher refreshrate

Post by ronco »

Hi katana,

thanks for testing :)

... i take a look on how to implement it in 2.0..

regards Felix

ronco
Posts: 317
Joined: Thu Aug 18, 2011 2:58 pm

Re: Servos with higher refreshrate

Post by ronco »

copterrichie wrote:This just be the answer to a prayer for my bicopters. I will give it a test and report back.

Hi copterrichie,

i added Bi copter HW PWM support to my branch.. would you like to test it?

it is here ->http://code.google.com/p/multiwii/source/browse/#svn%2Fbranches%2Fronco

you will need a GUI of the current shared trunk

you can activate it in config.h (HW_PWM_BI_SERVOS) .. refreshrate is the above chosen (50-300)

Code: Select all

  /***********************             HW PWM Servos             ***********************/ 
    /* HW PWM Gimbal for Arduino Mega moves:*/
    //Pitch = pin 44
    //Roll  = pin 45

    //#define MEGA_HW_GIMBAL
   

    /* HW PWM Bi Servos
    only for Promicro(atmega32u4's) and Mega. dont activate it on a promini*/
    // on the promicro the bi servo pins stays the same.. pin 5(bi_right) & 6(bi_left)
    // on the mega the pin 2 moves to pin 7.. pin 7(bi_right) & 6(bi_left)
    //#define HW_PWM_BI_SERVOS


regards felix

copterrichie
Posts: 2261
Joined: Sat Feb 19, 2011 8:30 pm

Re: Servos with higher refreshrate

Post by copterrichie »

I just did a search and seems there are some servos out there that can handle rates as high as 560hz, anyone have an idea of which brand can do handle these rates?


User avatar
Hamburger
Posts: 2578
Joined: Tue Mar 01, 2011 2:14 pm
Location: air
Contact:

Re: Servos with higher refreshrate

Post by Hamburger »

tested 300Hz on TRI with one digital servo and 328p mcu - seems to work, no intermittent servo yitter yet.

Maybe add a check to def.h to prevent more than one of the 3 options activated? Not sure which one wins otherwise.

tanaket
Posts: 1
Joined: Thu Jan 03, 2013 6:21 pm

Re: Servos with higher refreshrate

Post by tanaket »

Hi Felix,

Hope this thread is still active... My name is Edson Tanaka. I live in Rio - Brazil. I started "playing" with multicopters recently. I have an bicopter prototype assembled for testing purposes (I don´t think it can really fly, may the next frame version...). My objective now is to analyse the reactions and performance of control board and components like servos and motors. The control board is an Arduino Mega, with gyro+accel MPU6050, a small breadboard with few components to match the 3.3V of gyro to 5V of Arduino. TX and RX are Futaba T7C. I´m using the Multiwii 2.1 on Arduino and looking the reactions visually and with MultwiiConf 2.1.

For now, I have everyhing working - motors running, servos going to the right directions, gyro responding properly and producing the reactions in motors and servos correctly. I didn´t made any PID tunning up to now - I´m using the defaut values. You must be thinking "Why this guy is posting here, if everything is nice?" The problem I have is an "old" (maybe not too old) problem: servo jitter - high in frequency and amplitude(20 to 30 degrees). I googled several threads talking about this problem. Some give solutions that I´m testing just now (capacitors, toroids, separated sources for each servo and other "recipes").

I also found this thread and the answer you gave to copterrichie, that I post partially below (I don´t know yet how to add the listing in a separate window...):

/* HW PWM Bi Servos
only for Promicro(atmega32u4's) and Mega. dont activate it on a promini*/
// on the promicro the bi servo pins stays the same.. pin 5(bi_right) & 6(bi_left)
// on the mega the pin 2 moves to pin 7.. pin 7(bi_right) & 6(bi_left)
//#define HW_PWM_BI_SERVOS

I checked that the MultiwiiConf 2.1 has the addition above is already inplemented.

In the listing above the comment indicate that (if I understood right) I have to connect the right servo in the digital pin 7 (instead of pin 2). I couldn´t find (but my programming skills are not good...) , where the pin 2 was changed to pin 7. I searched in config.h and def.h with no success. I could find where the pin 2 is connected - SERVO 6. I looked also the code in the trunk site (it appears to be version 2.0...maybe...) and couldn´t find too. I understand that you changed to pin 7 due to some timing problems that can occur on pin 2 in Arduino Mega interrupt function (and produce some jitter...).

I didn´t test yet the current version (moving the servo to pin 7). I started reading the code change and trying to figure out what this would affect the bicopter, but when I coudn´t find the pin 7 in the code I decided to write this e-mail to you.

Thanks a lot for your time and if I can help in any way, please inform.

Regards,
Edson

Post Reply