How to create a calibration-subroutine for multimap-values?

At first i want to thank all the contributors who keep this community alive since years. I am reading here since months, started coding 8 weeks ago, and had a fairly satisfying experience because there is so much information available for free!

My code is supposed to control a servo depending on a rangefinder readout. Since i need a logarithmic behaviour i started using the multimap function, wich works like a charm. The next step is to create a subroutine that allows me to change the out-Values of the multimap, in order to calibrate the values the servo gets depending from the measured distance. I want to use an encoder + lcd with a little menu to accomplish that without a computer.

My plan was to start with the smallest in-value, display it on the lcd and use the rotary encoder to change the corresponding out-value and confirm it with the button of the encoder. After this step the lcd shows the next biggest in-value and the out-value is calibrated again, and so on untill the biggest in-value is reached. Then the calibration will be stopped and the normal program shall start running.

My first question would be how to access the values in the out-table? There must be a function but i didn’t find it yet. I would be happy if someone could point me in a direction - i am not shy of reading…

This is the actual code i am refering to:

``````// Controlling a servo position using a distancesensor via I2C
// hopsenrobsen, Koeln, Germany 01/2015

#include <Servo.h>
#include <Wire.h>
#include <map.h>

Servo myservo;                                                                                   // create servo object to control a servo
const int potpin = 0;                                                                            // analog pin used to connect the potentiometer
int potVal;                                                                                      // variable for the potentiometerreadout
int potValMap = 0;                                                                               // mapped potivalue
int receivedValue = 100;                                                                         // variable to read the value of the rf_sensor
int myservoVal = 90;                                                                             // variable for the Servoposition
int degree = 0;
int out[] = {  5, 15, 23, 30, 36, 47, 57, 69, 80, 90, 99,115,127,143, 155};
int in[]  = { 40, 50, 60, 70, 80,100,120,150,200,250,300,400,500,700,1000};

void setup()
{
myservo.attach(9);                                                                             // attaches the servo on pin 9 to the servo object
Wire.begin();                                                                                  // Start I2C
Serial.begin(115200);                                                                          // starting serial connection
}

void loop()
{
Wire.beginTransmission(rf_address);                                                            // listen to rf on i2c-bus
int available = Wire.requestFrom(rf_address, (int)2);                                          // requesting 2byte data from the rf on the i2c-bus
if(available == 2)                                                                             // if 2 bytes available
{
receivedValue = Wire.read() << 8 | Wire.read();                                              // connecting two bytes back together because the rf sends 16bit integer
}
else
{
Serial.print("errorcondition!");
Serial.println(available);
}
Wire.endTransmission();
delay(5);

potValMap = map(potVal, 0, 1023, -200, 200);                                                   // map potivalue
myservoVal = multiMap(receivedValue, in, out, 15);                                             // use the multimap
myservo.write(myservoVal);                                                                     // sets the servo position according to the multimap
}
int multiMap(int val, int* _in, int* _out, uint8_t size){
if (val <= _in[0]) return _out[0];                                                             // take care the value is within range
if (val >= _in[size-1]) return _out[size-1];                                                   // val = constrain(val, _in[0], _in[size-1]);
uint8_t pos = 1;                                                                               // search right interval  _in[0] allready tested
while(val > _in[pos]) pos++;
if (val == _in[pos]) return _out[pos];                                                         // this will handle all exact "points" in the _in array
return(val - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];  // interpolate in the right segment for the rest
}
``````

My first question would be how to access the values in the out-table?

I assume that you are referring to the values in the out array.

If that is the case then the first value in the array is out[0], the second is out[1], the third is out[2] and so on. Is that the information that you want ? If not, please explain in more detail.

TimonLee:
My first question would be how to access the values in the out-table?

Isn’t this the out-table?

``````int out[] = {  5, 15, 23, 30, 36, 47, 57, 69, 80, 90, 99,115,127,143, 155};
``````

Can’t you access its values in the customary fashion?

`````` for (int i=0; i < 15; i++) {
Serial.println(out[i]);
}
``````

Maybe I don’t understand the question.

Yeah - that is partly what i mean. I just don't know how i can "access" (overwrite) the values. Wich command i could use... I suppose I need something like a pointer to go through the array, in order to write or overwrite the existing old value in the out-array with the one set by the encoder. I hope this clears things up? I am a noob still..

@tmd3

The multimap works, i can access the values. I just don't know how to overwrite them in a calibration-like style. What do i have to do in order to exchange f.e. the out[0] with another value i set with the encoder? Thx!

I imagined it like this: Long press of encoderbutton starts a subroutine, the smallest in-value is displayed "in[0]", turning of the encoder makes the servo go to the desired position, pressing of the encoder overwrites the old "out[0]", from then on all the same up to in[14]

Maybe this clears things up..

To set out[0] to a value just do

``````out[0] = value;
``````

and so on.

This solution is way over my head! - Just joking.. I was convinced it would be much more complex, less easy. Dough. Will try and post my progress. Thx to all!

Just make sure that you don’t try and write to more array levels than you have declared. The program will let you do it but it is likely to overwrite something important if you do. The problem is often caused but declaring an array with an explicit number of places then using that number in a for loop starting at zero and ending at that number. However, array indices start at zero and it it is easy to forget and write to one too many.