Reset Analog Calibration?

Hello,

I am trying to calibrate an analog input as defined in http://arduino.cc/en/Tutorial/WhileLoop, where it calibrates only when a certain input is high.

void calibrate() {
  // turn on the indicator LED to indicate that calibration is happening:
  digitalWrite(indicatorLedPin, HIGH);
  // read the sensor:
  sensorValue = analogRead(sensorPin);

  // record the maximum sensor value
  if (sensorValue > sensorMax) {
    sensorMax = sensorValue;
  }

  // record the minimum sensor value
  if (sensorValue < sensorMin) {
    sensorMin = sensorValue;
  }

The problem is, from what I can tell, that if I calibrate it once, I get values between 100 - 400.

But, if I then calibrate it a second time, and get values between 200 - 300, there’s nothing to clear the old values of sensorMin, and sensorMax.

I figured that if there was something in the ‘calibrate’ routine that reset these values, then that would fix the problem. But it also clears it everytime it loops through the routine.

My thoughts are that if there was something like a one-shot that I could use, then it would reset the values only once for every time I want to calibrate. I can’t find a way to only do a command only once.

If anybody has any suggestions on what I should do, I would greatly appreciate it. Also any information on WHY the code works would also be appreciated (I’d rather learn something than just type in a code and go).

Thanks,
Joshhua

If anybody has any suggestions on what I should do, I would greatly appreciate it.

There is nothing in that code snippet that matches your problem statement. Therefore the problem must be in some other part of the code. Post all of your code, and we can help you find the problem.

I can't find a way to only do a command only once.

Stuff done in setup is only done once. There are ways, using counters and/or boolean flags to limit when stuff is done in loop, too.

Hello,

Sorry for the delayed reply. I’d explain, but trust me, you don’t want to know.

Anyway, here is the entire code…

/*
  Conditionals - while statement
 
 This example demonstrates the use of  while() statements.
 
 While the pushbutton is pressed, the sketch runs the calibration routine.
 The  sensor readings during the while loop define the minimum and maximum 
 of expected values from the photo resistor.
 
 This is a variation on the calibrate example.
 
 The circuit:
 * photo resistor connected from +5V to analog in pin 0
 * 10K resistor connected from ground to analog in pin 0
 * LED connected from digital pin 9 to ground through 220 ohm resistor
 * pushbutton attached from pin 2 to +5V
 * 10K resistor attached from pin 2 to ground
 
 created 17 Jan 2009
 modified 4 Sep 2010
 by Tom Igoe
 
 This example code is in the public domain.

 http://arduino.cc/en/Tutorial/WhileLoop
 
 */


// These constants won't change:
const int sensorPin = A2;       // pin that the sensor is attached to
const int ledPin = 9;           // pin that the LED is attached to
const int indicatorLedPin = 13; // pin that the built-in LED is attached to
const int buttonPin = 2;        // pin that the button is attached to


// These variables will change:
int sensorMin = 1023;  // minimum sensor value
int sensorMax = 0;     // maximum sensor value
int sensorValue = 0;         // the sensor value


void setup() {
  // set the LED pins as outputs and the switch pin as input:
  pinMode(indicatorLedPin, OUTPUT);
  pinMode (ledPin, OUTPUT);
  pinMode (buttonPin, INPUT);
}

void loop() {
  // while the button is pressed, take calibration readings:
  while (digitalRead(buttonPin) == HIGH) {
    calibrate(); 
  }
  // signal the end of the calibration period
  digitalWrite(indicatorLedPin, LOW);  

  // read the sensor:
  sensorValue = analogRead(sensorPin);

  // apply the calibration to the sensor reading
  sensorValue = map(sensorValue, sensorMin, sensorMax, 0, 255);

  // in case the sensor value is outside the range seen during calibration
  sensorValue = constrain(sensorValue, 0, 255);

  // fade the LED using the calibrated value:
  analogWrite(ledPin, sensorValue);
}

void calibrate() {
  // turn on the indicator LED to indicate that calibration is happening:
  digitalWrite(indicatorLedPin, HIGH);
  // read the sensor:
  sensorValue = analogRead(sensorPin);

  // record the maximum sensor value
  if (sensorValue > sensorMax) {
    sensorMax = sensorValue;
  }

  // record the minimum sensor value
  if (sensorValue < sensorMin) {
    sensorMin = sensorValue;
  }
}

This code is verbatim of the Tutorial on the while loop. Which just happens to outline exactly what I need.

If I understand the code correctly, and per my tests, if I ‘calibrate’ the sensor a second time, and the range is smaller and contained in the range set by the first calibration, there is nothing to overwrite the original values. ( I hope that made sense?)

Anyway, am not experienced to know how to do this.

My thoughts are is that at the beginning of the ‘calibrate’ routine that reset these values, then it could calibrate it the way I want. However I do not know how to make it do this only once, per initialization of the calibrate routine.

I know that in the world of PLC’s that there is a one-shot timer, but don’t know of a comparable thing to the arduino. There may very well exist such a thing, but I do not know what to search for to find it.

As usual, any help is greatly appreciated.

Thanks,
Joshua

Wouldn't it work to just move your while statement into the setup() function accomplish what you want? The setup function only runs once at power up or reset states while the loop function cycles forever.

Lefty

Lefty,

Let me make sure I understand you right.

You're suggesting I take the code from the calibrate routine and move it into the setup routine. Then in the loop code, instead of calling on calibrate, call on setup?

Joshua

Richard,

Thanks for the reply.

Here is what I am wanting to do. I have an old trainer control for an rc airplane. The potentiometers and switches on this controller are broken straight out to a db-15 plug, of which I have a matching female connector. Here is the problem, the potentiometers have only two of the leads connected, making it basically a variable resistor, similar to a LDR. So, out of this I connect it to a voltage divider so I can input this into my analog input. Also, the potentiometer is not used to its full outer limits, only about 50% of the 'throw' is being used.

I would like to use these potentiometer, and make it scale to the full 0-1023, or 0-255, etc... Basically I don't want to take this into my analog input, and only receive values between 500-800. I don't know if you are familiar with these types of controllers, but they have a 'trim' for each pot, that allows you to tweak the output, to compensate for mechanical things on the airplane.

According to the sketch as posted above, when a certain input is high(switch on the controller) it will look for the highest and lowest values. If I understand it correctly, it starts at the beginning of the sketch being run, with the lowest value set to 1023, and the highest value set to 0.

If, then, it sees a value lower than 1023, it sets this as the lowest value, and if it sees a value higher than 0, it sets it as the new highest value. It then maps these values to the full 0-1023, which I can then use later as desired.

Here's the problem scenario:

The sketch runs; The lowest value is set to 1023, and the highest value is set to 0; I flip a switch, which tells the program to 'calibrate'; I move my pot up and down, which outputs a voltage; The lowest voltage output is 1 volt; The highest voltage output is 4 volts; This equates to a 'raw' analog reading of let's say 200-900; This overwrites the original high and low values to 200-900; I flip the switch off, and the program exits the calibrate routine, and runs the rest of the code;

Great.

Here's where the problem is...

Remember the lowest and highest values are set to 200 - 900; I, a second time, flip the switch which tells the program to calibrate, again; I now move my pot, up and down again, but this time, there is a smaller range; This outputs a voltage between 2-3 volts; This equates to a 'raw' analog input of let's say 400-700; Now the calibrate is looking for a value LOWER than 200, however the lowest the value got, this time, is 400 - the lowest value variable is not overwritten;

The same thing happens for the high value.

It's looking for a value HIGHER than 900, however, the highest value, this time, is only 700, so, again the value is not overwritten.

My theoretical remedy for this, is every time the calibrate function is called upon, the low and high values are reset to 1023, and 0, respectively.

However, the problem is, every time the it loops through the code it resets the values. You would have to go through the lowest and highest values in the amount of time it takes to run 8 or so lines of code - impossible.

I can't think of anyway to only reset the values only the first time it is run.

Joshua

It does seem like you are overcomplicating the situation, but I'm not really clear on that. No matter how you scale or map the raw values in software, you will still end up with the same resolution (discrete number of possible steps) as the raw count range. Only by electrical scaling (opamp to amplify and offset) prior to the analogRead can you come up with the max 1023 counts of resolution, if that is one of your goals.

Lefty