analog poti remove jitter?

hi all,

I have an analog poti with values from 0 to 1024.

I just have to check in which direction the poti is moving and how fast.

I must not use an encoder, because it has to be a fixed range for the haptics.

certain positions give me jitter +-1

deviding the int input by 10 and smoothing the result it is better.

but when I hit that sweet jitter spot it jitters so fast, the smoothing becomes worthless.

can you guys give me a hint on how to solve this by programming?

thanks,

Achim

Shift right 1 then shift left 1. That will kill the +/- 1 in 2 cycles. Or mask bit 0 and do it in 1.

have you tried running a "moving average filter" on your input data? the moving average filter very good for many applications and delivers great results for reducing random white noise while keeping a sharp step response

see Running Average for ideas

GoForSmoke: Shift right 1 then shift left 1. That will kill the +/- 1 in 2 cycles. Or mask bit 0 and do it in 1.

that's a nice trick!

Shift right 1 then shift left 1. That will kill the +/- 1 in 2 cycles.

Will it? Considering that the range of values is 0 to 1024, I'd expect to have to use an int. Shifting that right and then left would take more than 2 clock cycles, I would have thought.

an & mask with 0xFFFE (--> 1111 1111 1111 1110) to drop the last bit is probably also more than 1 cycle because of the 2 bytes unless working with a union and masking only the second byte

GoForSmoke: Shift right 1 then shift left 1. That will kill the +/- 1 in 2 cycles. Or mask bit 0 and do it in 1.

could you elaborate that? I'm quite the noob.

Divide the value by 2, then multiply the result by two.

we're talking about dividing integers and disgerarding the remainder?

9 / 2 = 4

but if it jitters to 10

10 / 2 = 5

fair point

have you tried a moving average filter option smooths things out?

J-M-L: an & mask with 0xFFFE (--> 1111 1111 1111 1110) to drop the last bit is probably also more than 1 cycle because of the 2 bytes unless working with a union and masking only the second byte

You only need to mask the low byte, high byte mask is & FF.

My bad on 2 cycles, I forgot to think word size.

In longer code, ADC dithering is solved by setting a deadzone of 1. Your analog input code watches the value play its silly game always while for the sketch it maintains a number that only ever changes by 2 or more, 3,4,5,20,500, but never change by just 1. Masking bit 0 does that very quickly.

GoForSmoke:
You only need to mask the low byte, high byte mask is & FF.

isn’t that what I wrote with my union comment?

dozerv8: could you elaborate that? I'm quite the noob.

This has a better solution but here goes:

A byte can be viewed as 8 binary digits (0 or 1) in a row starting with bit 7 (value 128) and going down to bit 0 (value 1). If we shift all the bits 1 bit to the right, whatever was in bit 0 goes off the end bye-bye. If we shift back 1 bit to the left then the other 7 bits go back to where they were and bit 0 will always be zero.

It works for 16-bit variables like int but takes more cycles since AVR chips only work on 8 bits at a time.

And this is a good tutorial that answers all. http://playground.arduino.cc/Code/BitMath

J-M-L:
isn’t that what I wrote with my union comment?

I don’t bother with the union. I have the address and if I need to offset then ++ it is.

GoForSmoke: I don't bother with the union. I have the address and if I need to offset then ++ it is.

sure - brute force :)

Note that

Arduino is little-endian ++ing an integer pointer does not add 1 to the pointer but 2.

so it does require a bit of thinking

Since I mask a byte and use an address to choose which, that problem gets cast away.

GoForSmoke: Since I mask a byte and use an address to choose which, that problem gets cast away.

OK never verified that the compiler behaves like this

so you are saying

int a;
int * ptr = &a;
*(ptr+1) &= 0xFE;

would mess around with the 2nd byte in memory of a?

need to test. :-)

tested - clearly not.

int x, a, y;
int *ptr;

void setup() {
  Serial.begin(115200);
  x = 0xFFFF;
  a = 0xFFFF;
  y = 0xFFFF;
  ptr = &a;

  Serial.println("before masking");
  Serial.print("x = 0x");
  Serial.println(x, HEX);
  Serial.print("a = 0x");
  Serial.println(a, HEX);
  Serial.print("y = 0x");
  Serial.println(y, HEX);

  *(ptr + 1) &= 0xFE;

  Serial.println("after masking");
  Serial.print("x = 0x");
  Serial.println(x, HEX);
  Serial.print("a = 0x");
  Serial.println(a, HEX);
  Serial.print("y = 0x");
  Serial.println(y, HEX);
}

void loop() {
  // put your main code here, to run repeatedly:

}

gives me in the console

before masking
x = 0xFFFFFFFF
a = 0xFFFFFFFF
y = 0xFFFFFFFF
after masking
[color=red]x = 0xFE
[/color]a = 0xFFFFFFFF
y = 0xFFFFFFFF

so I messed up somewhere else in memory :)

curious about what you meant

Are you being obtuse or dense? Did I write int or byte? Oh yes… byte.
Go on, make more strawmen and when they fall over, act like that was my code.

Actually the smart thing to do is test the hardware to get byte order first.

void setup( void )
{
  Serial.begin( 115200 );
  Serial.println( "\nserial connected..." );
  byte *t;

  unsigned long u32 = 0x11121314;
  t = (byte *) &u32;
  Serial.print( "\nunsigned 32 bit " );
  Serial.println( u32, HEX );
  for ( byte i = 0; i < 4; i++ )
  {
    Serial.println( *( t + i ), HEX );
  }
  unsigned int u16 = 0x2526;
  t = (byte *) &u16;
  Serial.print( "\nunsigned 16 bit " );
  Serial.println( u16, HEX );
  for ( byte i = 0; i < 2; i++ )
  {
    Serial.println( *( t + i ), HEX );
  }

  u16 = 0xFFFF;
  t = (byte *) &u16;
  *t &= 0xFE;
  Serial.print( "\nunsigned 16 bit " );
  Serial.println( u16, HEX );
  Serial.print( "low byte &= 0xFE makes " );
  Serial.println( u16, HEX );
}

void loop( void )
{

}

serial connected…

unsigned 32 bit 11121314
14
13
12
11

unsigned 16 bit 2526
26
25

unsigned 16 bit FFFE
low byte &= 0xFE makes FFFE

Well not sure why your answer feels impolite and aggressive , but I guess that is cultural and typical written miscommunications syndrome when two trains of thoughts are not aligned in a asynchronous discussions.

So for the record: no - I was genuinely trying to understand what you said.

I was still on my idea from this thread that the OP is receiving integers and thus not a byte. And I probably got lost in translation as I understood you were saying that no need for a union to address LSB and MSB easily, if he were to mask with a byte the integer value designated by an integer pointer that was possibly offset, then the compiler would "get it" and cast the pointer in the right way (like a char pointer I had guessed so that a +1 would address the second byte of the int)

I thought that would be quite an interesting news if that were to be correct so I went to ask the question to you and as I was writing it down I said to myself what they heck - let's try and see.

Given your reaction that definitely was not what you had in mind :) but you totally misread what my train of thoughts.

So yes agree that with a byte pointer and knowing about the indianess of the platform you can do it which is somewhat similar to using a union and letting the compiler handle the byte pointers for you.