Pages: [1]   Go Down
Author Topic: Calculating if I'm within 10% of the center of a pot  (Read 835 times)
0 Members and 1 Guest are viewing this topic.
South East USA
Offline Offline
God Member
*****
Karma: 5
Posts: 651
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This one's got me a bit stumped.  On power up, I want my bot to wait until the steering mechanism is within 10% of 'neutral'
Here's some variables I've got assigned to the min/max readings of the steering POT
steering.left
steering.right

steeringVal() is another function that returns the current reading of the POT

I'd like to make a boolean that will return TRUE if the steering is within 10% of center, or FALSE is it's not
This is as far as I got, but I'm not really sure about it...

Code:
boolean StraightAhead() {  //returns true if within 10% of center
  int steeringRange = abs(steering.left - steering.right); //the total range of the steering POT
  int steeringCenter = steeringRange / 2;  //the neutral steering position
  int tenPercent = steeringRange * .01;  //10% of the range, I think
  if (abs(steeringVal() - steeringCenter) < tenPercent) return true;
  else return false;
}
Logged

Offline Offline
Edison Member
*
Karma: 9
Posts: 1016
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Are the steering.left and steering.right the raw values from the analogRead() functions ?
Or are they calculated values from 0 to 180 (the degrees for the pot) ?

I assume they are the raw analogRead() values.
Is steering.left always the lower value, or could steering.left be the lower value ?

How do you use the 10%. Do you want the range to be from -5% to +5% around the center ?

I see 3 problems:
(1) Your center is not the range divided by two, but you have to add the steering.right or steering.left (whatever is the lowest value).
(2) Ten percent is "0.1", you use ".01" which is 1%.
(3) A value of "0.1" or ".01" is a floating point value, and you use integers to calculate it. That is not possible.

I used many variable in the next example, to show what is going on.
Code:
// example, not tested

boolean StraightAhead( void) {
  int lowest, range, middle;
  int steering, limit_low, limit_high;
 
  lowest = min (steering.left, steering.right);
  range = abs (steering.left - steering.right);
  middle = lowest + (range / 2);
 
  limit_low = middle - (range / 20);       // 5% lower
  limit_high = middle + (range / 20);     // 5% higher
 
  steering = steeringVal();
 
  if (steering > limit_low && steering < limit_high)
    return (true);
  else
    return (false);
}
« Last Edit: February 02, 2013, 05:03:36 am by Krodal » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


percentiles can be calculated with weighted average
// in int math look out for overflow.

Code:
boolean straight(float margin)  // 0.10
{
  steering = steeringVal();
  if (steering < (left*(0.5 + margin) + right*(0.5 - margin)) )   // becomes  left  * 0.6 + right * 0.4
  {
    return false;
  }
  return steering > (left*(0.5 - margin) + right * (0.5 + margin));  // becomes left * 0.4 + right * 0.6
}

optimized for +-10% in integer math
// as steering and  left and right are max 1024 (analog read) the peak value of the math is 5120 so will fit in an int perfectly
// all divisions are replaced by multiplications.
Code:
boolean straight(void)
{
  steering = steeringVal();
  if ((steering*5) < (left*3 + right*2))
  {
    return false;
  }
  return (steering*5 > (left*2 + right*3) );
}
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

South East USA
Offline Offline
God Member
*****
Karma: 5
Posts: 651
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Are the steering.left and steering.right the raw values from the analogRead() functions ?
Or are they calculated values from 0 to 180 (the degrees for the pot) ?

I assume they are the raw analogRead() values.
Is steering.left always the lower value, or could steering.left be the lower value ?

How do you use the 10%. Do you want the range to be from -5% to +5% around the center ?

I see 3 problems:
(1) Your center is not the range divided by two, but you have to add the steering.right or steering.left (whatever is the lowest value).
(2) Ten percent is "0.1", you use ".01" which is 1%.
(3) A value of "0.1" or ".01" is a floating point value, and you use integers to calculate it. That is not possible.

I used many variable in the next example, to show what is going on.
Code:
// example, not tested

boolean StraightAhead( void) {
  int lowest, range, middle;
  int steering, limit_low, limit_high;
 
  lowest = min (steering.left, steering.right);
  range = abs (steering.left - steering.right);
  middle = lowest + (range / 2);
 
  limit_low = middle - (range / 20);       // 5% lower
  limit_high = middle + (range / 20);     // 5% higher
 
  steering = steeringVal();
 
  if (steering > limit_low && steering < limit_high)
    return (true);
  else
    return (false);
}

Thanks, yes, I see all 3 problems, and your were correct. 
steeringVal(), steering.left, and steering.right  are all raw analog readings, though they typical range from 500-600 min/max, not 0-1024.  So I think what you've come up with looks like it will work.  I'll make a serial monitor debug loop and check it out.  Thanks.
Logged

South East USA
Offline Offline
God Member
*****
Karma: 5
Posts: 651
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's what I ended up with:
Code:
boolean StraightAhead( void) {
  int lowest, range, middle;
  int limit_low, limit_high;
  lowest = min (steering.left, steering.right); //the lowest of the 2
  range = abs (steering.left - steering.right); //the range from left to right
  middle = lowest + (range / 2);  //the center steering value
  limit_low = middle - (range / 20);       // 5% lower than center
  limit_high = middle + (range / 20);     // 5% higher than center
  int curentVal = steeringVal();
  if (curentVal > limit_low && curentVal < limit_high)
    return (true);
  else
    return (false);
}


What is the difference between these two lines?  Are they the same?
Code:
boolean StraightAhead( void) {
boolean StraightAhead() {
Logged

Offline Offline
Edison Member
*
Karma: 9
Posts: 1016
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

'void' indicates that no parameter is used. In this situation void means 'nothing here'.
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17263
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What is the difference between these two lines?  Are they the same?

Code:
boolean StraightAhead( void) {
boolean StraightAhead() {

They are functionally equivalent. One is explicitly stating that there are no variables passed to the function, the other implies it by omission. Not sure what the C/C++ standards say but the present gcc compiler is happy with either.

Lefty
Logged

South East USA
Offline Offline
God Member
*****
Karma: 5
Posts: 651
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks for the info.
Logged

Offline Offline
Faraday Member
**
Karma: 61
Posts: 2879
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What is the difference between these two lines?  Are they the same?

It's my understanding that the ( void ) was originally required in function declarations but
not in function definitions.

But now, either appears to be OK.
Logged

Pages: [1]   Go Up
Jump to: