sareph / th9x

Automatically exported from code.google.com/p/th9x
Other
0 stars 0 forks source link

Stick latency #46

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Move stick
2. up to 80mSec delay before servo settles
3.

What is the expected output? What do you see instead?
Instant settling of servo

What version of the product are you using? On what operating system?

Please provide any additional information below.
There is a parallel project done by Erezz (er9x on google code) using the 
th9x_R135 as a basis. This codebase has implemented more advanced features
(more for advanced pilots) but stumbled upon a problem in the basic thus code. 
The ADC averaging follows a hyperbolic curve, and reaches 1% accuracy after 
128mSec. This is caused by a/ the algorythm, and b/ the averaging (the divde by 
16 in the routine).
It is obvious this is a crucial piece of code (since it is processed very 
often, and is part of the real time behaviour of the transmitter), but 
significant latency improvements could be achieved by simply changing the value 
of 16 into something lower. A value of 4 (replace the /16 by >>2) would 
eliminate it (>>2 equals /4), but may cause more ADC noise. Or optimize for >>3 
(equals /8)

See also : http://www.rcgroups.com/forums/showthread.php?t=1266162&page=45

This shows oscilloscope pictures of the behaviour. 

Original issue reported on code.google.com by harm.del...@echostar.com on 2 Sep 2010 at 7:41

GoogleCodeExporter commented 9 years ago
This may be a solution (copy from issue 79 in the er9x thread)

ISR(ADC_vect, ISR_NOBLOCK)
{
  static uint8_t  chan;
  static uint16_t s_ana[8];
  static uint16_t ss_ana[8];
  static uint16_t sss_ana[8];

  ADCSRA  = 0; //reset adconv, 13>25 cycles
  //if(! keyState(SW_ThrCt)){
  s_anaFilt[chan] = (s_anaFilt[chan] + sss_ana[chan]) >> 1;
  sss_ana[chan] = (sss_anaFilt[chan] + ss_ana[chan]) >> 1;
  ss_ana[chan] = (ss_anaFilt[chan] + s_ana[chan]) >> 1;
  s_ana[chan] = (ADC + s_ana[chan]) >> 1;
    //}
  chan    = (chan + 1) & 0x7;
  ADMUX   =  chan | (1<<REFS0);  // Multiplexer stellen
  STARTADCONV;                  //16MHz/128/25 = 5000 Conv/sec
}

This would be 4.3 x faster, and give the same rejection.

Original comment by harm.del...@echostar.com on 2 Sep 2010 at 8:55

GoogleCodeExporter commented 9 years ago
use similar algorithm, with adjustable filter depth: 0,1,2,3

  uint16_t v=ADC;

  uint16_t *filt = (uint16_t*)(s_filtBuf + (uint8_t)(chan*4*2));
  for(uint8_t i=g_eeGeneral.adcFilt; i>0; i--,filt++){
    uint16_t vn = *filt / 4; //0,16,23,28 vals to 99%
    *filt += v - vn; // *3/4
    v=vn;
  }
  asm("":::"memory"); //barrier saves 6 asm-instructions
  s_anaFilt[chan] = v;

Original comment by th...@t-online.de on 8 Sep 2010 at 10:56

GoogleCodeExporter commented 9 years ago
See this comment pure as a comment, and not as criticism.

The above algorythm is faster, but does not have equal rejection. Above filter 
has 75% glitch rejection (the /4), where the origional in R141 (has /16) and 
alternate given by me ( /(2^4) )give 94% rejection.

However, I haven't seen any specification that the filter needs to reject 
glitches by 94%, so above algorythm may be fully adequate for the task. We will 
see in testing once we have a released label again.

Original comment by harm.del...@echostar.com on 9 Sep 2010 at 7:53