Quantcast
Channel: MSP430 Technical Forums
Viewing all articles
Browse latest Browse all 2077

Analog Input Smooth - Comparisons Don't Work

$
0
0

Hey there guys. First post in a long time.

 

I find myself developing once again on an MSP430G2553 chip on a Rev 1.4 Launchpad and I am trying to take samples from the on-chip ADCs using Energia.

 

It's not secret that the on-chip ADCs are quite unstable (very accurate perhaps?), I don't get anywhere near the kind of jitter I see when using the MCP3008 (10-bit, 8-channel ADC converter IC). Regardless, I am very frustrated with the section of my code that deals with smoothing the signal from analog controls.

 

I am sampling 4 ADC values and averaging it, no problem.

 

What really frustrates me is that when I try to check if the new value is within a certain sensitivity (range) of the last recorded value, I have to do a strange work-around or else I get constant resends as if I'm not even checking if the value is in the certain range.

 

In other words, I cannot use the compare operators greater than, less than, greater than/equal to, and less than/equal to, in order to check if the new ADC value is within a certain range of the old recorded value.

 

To illustrate this, I will include the code I use to do this and show you what I would like to do (which doesn't work) and what I do currently (which still results in some glitches)

 

Just for reference, this is what the Control class looks like:

class Control
{
 public:
  //Identification information
  int pin;      //Sets the pin to be used by the control
  int ID;       //Identification number (0-31)
  
  //Data processing variables
  int value; //Stores the current value
  int oldValue; //Stores the old value (for preventing constant resends)
  int counter; //Counter used for averaging
  int average; //Value use for calculating average
  
  int sensitivity; //Value used for setting sensitivity (a variable in smoothing algorithm) @todo
  
  //Constructor
  Control(int nID, int nPin, int nSensitivity);
  
  //Methods
  int      Read(void);    //Reads the value of the control
  boolean  isNew(void);   //Returns true if the value has updated (within a reasonable range, the sensitivity)
  void     Send(void);    //Transmits the control change to the computer for processing
  
};

And this is what the Control.Read() function does (it includes the average code)

int Control::Read(void)
{
    int pinVal = analogRead(pin);
    if(pinVal == 1023 || pinVal == 0) //it is max/min
    {
      return pinVal; //I do this so that mins/maxs can be sent anyway. It's important that absolute mins/maxs are sent.
    }
    
    if(counter != 3) //Averaging counter that's stored on the class
    {
      average += analogRead(pin);
      counter++; //Increment Counter
      return 1025; //Not ready value (outside ADC range)
    }
    else
    {
      average /= 4; //Divide by 4 to average
      counter = 0; //Reset counter
      return average;
    }
  }
}

Code that I would like to use:

boolean Control::isNew(void) 
{
  value = Read(); //Set value of control

    if(value == 1025) //Not ready
       return false;
       
    //First check for maxs/mins (to prevent resending)
    if(value == 1023 || value == 0) //it is max/min
    {
      if(value != oldValue) //max/min was not sent already
      {
        oldValue = value;
        return true;
      }
    }
    //Check if its within sensitivity setting
    if(value >= (oldValue-sensitivity) || value <= (oldValue+sensitivity)) //This does nothing to smooth input (constantly returns true, even when it shouldn't)
      return false; //Still within sensitivity, report false
    else
    {
      oldValue = value; //It's changed more than the sensitivity, update values and report true
      return true;
    }
  }
  return false; //If it hasn't returned true by now, return false
}

Code that I use right now...

boolean Control::isNew(void) 
{
  value = Read(); //Set value of control
    if(value == 1025) //Not ready
       return false;
       
    //First check for maxs/mins (to prevent resending)
    if(value == 1023 || value == 0) //it is max/min
    {
      if(value != oldValue) //max/min was not sent already
      {
        oldValue = value;
        return true;
      }
    }
    boolean within5 = false; //Please ignore the irrelevant name of this variable
    int checkVal = 0;
    //Then check if it's within 15 of previous value
    for(int i=0;i<15;i++)
    {
      checkVal = value + i;
      if(checkVal == oldValue)
      {
        within5 = true;
        break;
      }

      checkVal = value - i;
      if(checkVal == oldValue)
      {
        within5 = true;
        break;
      }
    }
    if(!within5) //Not within 15
    {
      oldValue = value;
      return true;
    }
  return false; //If it hasn't returned true by now, return false
}

The main loop does something like this:

  if(control_1.isNew())
  {
    control_1.Send(); //Simply prints the value to the serial line
  }

Similarly, I have tried to see if the new ADC value is above a certain threshhold as to count it as a maximum value. Above a certain value (like 1015) the sensitivity check becomes erratic, it sends new values even if they're within (for example) 2 of the last value.

 

The code I used was:

if(value > 1015) //If it's above a certain threshhold
  value = 1023;  //Count it as a maximum

The kind of output I would get is still like:

1020
1022
1018
1023
1023
1020

The sensitivity is normally set to within 10-20 for the on-board ADC. For controls connected to the MCP3008, the sensitivity is about 5, it is as stable as a rock.

 

What is going on? Why can't I compare these values? Is it related to the type of variable I store the value in? I have tried changing the related variables to unsigned integers and it has no effect.

 

It has had me pulling my hair out. I hate inefficient code on MCUs and using for loops simply to check if a value lies within some range seems pretty inefficient to me.

 

I'll post the finished project when I'm done.

 

Thanks guys!


Viewing all articles
Browse latest Browse all 2077

Trending Articles