handling Continuous data with byte roll over

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I have an application that can only put a distance moved on a 8 bit value.  the position is sampled  at a given poll rate and for obvious reasons the slower the poll rate is the more problematic or "less effective" it is.  The application will sample the value and store an old value. then on the next consecutive read it subtracts, hence distance moved.

 

Issue one, if the last point was 250 and the distance  traveled was 15, it will calculate a large value in the wrong direction.

250 - (250 + 15). which  means 250 - 5 because the byte wraps. the immediate  way of fixing this was to not calculate a large distance. So in this case its 245, so if the abs value > 200, we ignore that read.  This works for a poll rate of 4ms. but if the poll rate is slower like 16ms, then the distance traveled could hit 200. So now we have this, 250 - (250 + 200) which means 250 - 190 making the value  60 but in the wrong direction.  This will not trigger the > 200 so it moves the wrong way.

 

So I'm wondering if there is a convention for this sort of thing I'm unaware of. I think the if value greater than 200 is more of  a hack. Maybe there is some simple way to deal with this.

A simpler more direction question would be to ask, if you have data that can move left or right represented in a integer. how do you handle the byte roll over.

 

 

 

 

 

 

Last Edited: Thu. Jul 7, 2022 - 10:35 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

how do you handle the byte role over.

Do you mean ROLL over? Or is it a real term for something I'm not aware of?

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the new reading is less than the last, then add 256 to the difference

 

had 200 now have 240, moved 240-200 =moved 40

had 200 now have 10, moved 256-200+10 =moved 66

 

If you need to go in both directions, then you need to restrict the range to 1/2 of the above , in each direction (essentially used signed values) and handle the rollover/under likewise.

 

role over.

roll over, you aren't an actor.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you need to go in both directions, then you need to restrict the range to 1/2 of the above , in each direction (essentially used signed values) and handle the rollover/under likewise.

 yes right I do need to know both directions. Unsure I follow your advice about halfing the range?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Note for C +/- signed values, you need to look at your compiler:

Strictly speaking, overflow of signed integers is undefined behavior. In practice however, most implementation use 2's complement representation for integers and wraparound will work how you describe.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

if the new value is less than the current value use another formula.

256-(old value - new value)

if the value is larger then it is (new value - old value)

if the values are the same distance can be 0 or 256 that will depend on you making sure you never have a distance larger than 255.........

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Use a larger int! Say int64_t

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Thu. Jul 7, 2022 - 07:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well if you only have an 8-bit "Distance Register" and you allow +VE & -VE movements then you can only support limits of -128 to +127 as the maximum distance moved between samples.

 

You would calculate this as:

uint8_t distancePrevious, distanceNow;
...
int distanceMoved = (int) (distanceNow - distancePrevious);

 

For the condition of very large speed that would overflow the -128 to +127 limit you cannot detect that. The only solution is to sample faster.

 

If however you can modify the actual detector then you can apply rules to detect or limit over-speed.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

S_K_U_N_X wrote:
Issue one, if the last point was 250 and the distance  traveled was 15, it will calculate a large value in the wrong direction.
But if you use uint8_t, 250 + 15 = 265 or 0x109. As the 0x100 in that won't fit in uint8_t the result is 0x09 so it "rolls over automatically" doesn't it ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If N-bit unsigned difference is outside the interval [pow(2,-N/2), pow(N/2)-1], then add or subtract pow(2,N) to get inside the interval.   This means if your system must keep changes in that interval.  If not, you need a bigger unsigned.

 

EDIT: fixed typos; and for example if your data comes in as uint8_t, then    int16_t diff = (new - old);  if (diff < -128) diff += 256 else if (diff > 127) diff -= 256;

Last Edited: Thu. Jul 7, 2022 - 04:45 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

S_K_U_N_X wrote:

...that can only put a distance moved on a 8 bit value...

 

Just to be clear...

 

1) Distance moved...so you have a relative count, as opposed to an absolute position, which simply indicates the number of 'steps' that your thing has moved in some direction?

 

2) Do you have any way of knowing whether your thing has moved in one direction as opposed to the other?

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the distance moved has to be restricted to 8 bits and the range has to be greater than 256,

the only real choice is to scale down the value.

 

'Tain't clear whether OP has a choice regarding the current position.

If so OP can just use a large enough register.

 

I am not entirely clear regarding OP's situation.

"the position is sampled  at a given poll rate"

means that the position comes from the outside world and the number of bits is sufficient.

Correct?

How many bits?

OP can choose the poll rate.

Correct?

 

What are the actual constraints on the format difference data?

Where do they come from?

Is 8-bit floating point a possibility?

What about a difference of differences,

something akin to acceleration?

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
Is 8-bit floating point a possibility?
Uncertain though 8-bit fixed-point is possible.

 

Fixed-Point Support | avr-gcc - GCC Wiki

Fixed-point Overflow | FAQ | CNL: User Manual

[third question]

Q: Why doesn't cnl::scaled_integer prevent/avoid/detect overflow?

...

via Further Reading | GitHub - johnmcfarlane/cnl: A Compositional Numeric Library for C++

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

S_K_U_N_X wrote:

 

I have an application that can only put a distance moved on a 8 bit value.  the position is sampled  at a given poll rate and for obvious reasons the slower the poll rate is the more problematic or "less effective" it is.  The application will sample the value and store an old value. then on the next consecutive read it subtracts, hence distance moved.

Issue one, if the last point was 250 and the distance  traveled was 15, it will calculate a large value in the wrong direction.

250 - (250 + 15). which  means 250 - 5 because the byte wraps. the immediate  way of fixing this was to not calculate a large distance. So in this case its 245, so if the abs value > 200, we ignore that read.  This works for a poll rate of 4ms. but if the poll rate is slower like 16ms, then the distance traveled could hit 200. So now we have this, 250 - (250 + 200) which means 250 - 190 making the value  60 but in the wrong direction.  This will not trigger the > 200 so it moves the wrong way.

 

So I'm wondering if there is a convention for this sort of thing I'm unaware of. I think the if value greater than 200 is more of  a hack. Maybe there is some simple way to deal with this.

A simpler more direction question would be to ask, if you have data that can move left or right represented in a integer. how do you handle the byte roll over.

 

If I understand, your device can travel long distances forward or back. When queried, it can report the current position relative to some place that we might as well call home, or position = 0. The position could be millions, billions, maybe more!! The problem is that the position query truncates the reported position so that you only get the low 8 bits.

 

So query for the 8 bit position value often enough that the new value will never be more than 127 away from the last. Presumably you know the maximum speed, so you can calculate how often you'll need to query the position to guarantee the distance traveled is never more than 127. If the the distance moved could be more than 127, then there is no possible way to tell if there was a rollover or in what direction; the distance cannot be calculated. It's impossible. Game over.

 

If you do query often enough that distance traveled is always less than 127, then you can identify rollovers in either direction and calculate a signed value for the distance traveled.

 

uint8_t current = 0, previous = 0; // results of query
int16_t distance = 0;

previous = queryposition(); // prime the pipeline

while(1)
{
    distance = current - previous;
    
    if( abs(distance) > 127)    // rollover
    {
        if(current < previous)  // forward rollover
        {
            distance += 256;
        }
        else                    // reverse rollover
        {
            distance -= 256;
        }
    }
    
    previous = current;
    
    // do something with calculated distance
}

 

Brian Fairchild wrote:

It's at this point that we really do need the OP to come back and engage with us. So many questions..........

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

If you convert the subtraction result of the 2 8-bit unsigned values to 8-bit signed, you will get the correct result as long as the distance moved between samples is 127 (MAX 8 BIT POSITIVE VALUE) or less.

 

In your example:  Previous encoder value = 250.  Next encoder value = 250+15 = 9 (with 8-bit rollover).

9 - 250 = 15

 

In the opposite direction,

250 - 9 = 241 (unsigned) = -15 (signed 8 bit)

Last Edited: Thu. Jul 7, 2022 - 10:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe it would help if the OP were to describe what the 8-bit variable is supposed to do. It has gotten quite confusing about absolute vs incremental distance, resolution vs maximum value, positive vs negative distance vs increment, and more. So, S_K_U_N_X, please write, for us, a description of the desired behavior. Forget about the algorithm, roll-over,  and other implementation details; just tell us what that variable is supposed to indicate!

 

Only then, can we sensibly talk about the issues that concern you. 

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Thu. Jul 7, 2022 - 11:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

gchapman wrote:
skeeve wrote:

Is 8-bit floating point a possibility?

Uncertain though 8-bit fixed-point is possible.

To be clear, I was wondering whether it would be sufficient for the application.

Clearly it can be done.

8-bit floating point should not be much harder to implement than 32-bit floating point.

If all else fails, one can use a 256-entry look-up table.

Its utility for this problem or any other is the issue.

Moderation in all things. -- ancient proverb