Go Down

Topic: adjust servo from current position using a pot (Read 960 times) previous topic - next topic

grantastley

Hi 

I have a servo that has its lower and upper limits setup in a callibrate function using a mapped value of a potentiometer analog input.  However the problem I am having is when I go back to recalibrate the servo, say I am calibrating the lower limit I would like the servo to move to the current lower limit and then use the potentiometer to adjust it from that position.
So rotating the pot clockwise would increase the LeftLowerTrimVal and rotating it counter clockwise would decrease the LeftLowerTrimVal.

The reason this is a problem is I do not want the servo to be able to move to a value outside the current set trims when entering the callibration mode but be able to move it outside the current set trims by rotating the pot.

The lower limit is stored in EEPROM with value LeftLowerTrimValE
The trims input is used to adjust the limits

below is the code used for one limit(trim) adjustment.

Code: [Select]
while(LeftLowerTrim==HIGH){
  AcceptVal=digitalRead(Accept);    //Read the digital input 9 - Accept 
  TrimVal=analogRead(Trims);        //Read the trim pot value
   
    LeftLowerTrimVal=map(TrimVal,0,1023,0,90);             //Scale input from 0 to 90
     
      //Need this to move to current EEPROM value - WingFoldLeft.write(LeftLowerTrimValE);
      //then use the pot to adjust it from this point.
      WingFoldLeft.write(LeftLowerTrimVal);                  //Move servo to current lower trim value set by the pot atm
       
        if(AcceptVal==HIGH){                                 //Only change LeftLowerTrimVal if accept is pressed
          EEPROM.write(LeftLowerTrimValE, LeftLowerTrimVal); //Stores value in EEPROM so it can be recalled once calibration mode is exited                                 
        }
      LeftLowerTrim=digitalRead(SetTrim1);                   //Check to see if setup selections conditions have changed
      delay(500);                                            //Allow time for servo to adjust to new position
}


Hope this makes sense as to what I am trying to do.

grantastley

What are peoples thoughts on the following code.  Should this do what I am trying to do?

Code: [Select]

while(LeftLowerTrim==HIGH){
AcceptVal=digitalRead(Accept);    //Read the digital input 9 - Accept 
TrimVal=analogRead(Trims);  //Read the trim pot value

WingFoldLeft.write(LeftLowerTrimValE);  //write servo to current lower trim value stored in EEPROM

InitialTrimVal=TrimVal; //Setup something to compare values to

delay(500);  //Allow time for trim pot to be adjusted

LowerMap=map(TrimVal, 0,TrimVal, 0, LeftLowerTrimValE);   //Map from 0 to the current trim pot value and current servo location (Lower end)
UpperMap=map(TrimVal, 90, TrimVal, 90 LeftLowerTrimValE); //Map from 90 to the curretn trim pot value and current servo location (Upper end)

//use the lower map if the initial trim value is larger then the current trim value (pot has been turnd down and input is less)
if (InitialTrimVal>LowerMap){
WingFoldLeft.write(LowerMap);
  if(AcceptVal==HIGH){                                 //Only change LeftLowerTrimVal if accept is pressed
    EEPROM.write(LeftLowerTrimValE, LowerMap); //Stores value in EEPROM so it can be recalled once calibration mode is exited                                 
  }
}

//use the upper map if the initial trim value is less then the current trim value (pot has been turnd up and input is more)
if (InitialTrimVal<LowerMap){
WingFoldLeft.write(UpperMap);

  if(AcceptVal==HIGH){                                 //Only change LeftLowerTrimVal if accept is pressed
    EEPROM.write(LeftLowerTrimValE, UpperMap); //Stores value in EEPROM so it can be recalled once calibration mode is exited                                 
  }
}

LeftLowerTrim=digitalRead(SetTrim1);                   //Check to see if setup selections conditions have changed
delay(200); //allow time for servo to move to new location
}

PeterH

I haven't understood the calibration procedure you're describing clearly enough to make any sense of the code.

I assume you have some external means for the user to start and end the 'calibration' process and I guess you intend to 'calibrate' one end setting at a time.

Can you describe in more detail what happens during the calibration in terms of the potentiometer and servo positions and movements? What are the initial positions? How do the movements of the pot affect the servo?

Make sure that you only update the EEPROM occasionally - I'd suggest just once at the end of the calibration process. The EEPROM has a limited life and if you write to it repeatedly you will eventually wear it out - and that can happen very quickly if you are writing to it frequently.
I only provide help via the forum - please do not contact me for private consultancy.

grantastley

#3
Jul 08, 2013, 01:47 pm Last Edit: Jul 08, 2013, 02:18 pm by grantastley Reason: 1
Hi
Yes the calibration mode is entered using a dip switch on a digital input, this begins a while loop which loops through all the different setup areas, more while loops(around 12 servos each with upper and lower end points to set.  All of which are entered by using another dip switch on another digital input.  This is why I only included one end setting of one servo.

What I would like to happen is when the setup area for a particular servo end point is entered (LeftLowerTrim in the example) the servo should move to the previous location stored in the EEPROM (LeftLowerTrimValE in this example).  From here you are able to move the servo using the pot.  If you rotate the pot clockwise the servo will rotate servo clockwise in a linear fashion and likewise if the pot is rotated counter clockwise the servo would rotate counter clockwise.  Once the new desired location is obtained press the accept button and the new value is stored in the EEPROM to be recalled once calibration mode is exited.

Yes I am aware about the EEPROM writes that is why I added the Accept button the new value will only be written to the EEPROM when this button is pressed (momentary pb)

If this is not enough detail please let me know.

P.S. I dug up a pot and ran the second lot of code posted, this does not work and the servo just jumps between LeftLowerTrimValE and LowerMap.  LowerMap value also does not change.  Thinking maybe I need a condition to only allow
Code: [Select]
InitialTrimVal=TrimVal; //Setup something to compare values to to occur once when the while loop is first ran?

In this code I am trying to use LowerMap and UpperMap to map the values of the pot from the current position to the lower and upper extremities of the input (0 and 1023) to a range of 0 to current servo location and current servo location to 90 (0 to 90 is the end point range available).  Then use an if statement to determine which way the pot has moved and adjust the servo location accordingly.

Any help, ideas, info would be greatly appreciated.

below is the full code I ran
Code: [Select]


#include <Servo.h>  //include servo libery
#include <EEPROM.h> //Allow to read and write to EEPROM

Servo WingFoldLeft;

int Accept=2;  //pin 2
int AcceptVal=LOW;

int Trims=3;  //analog pin 3
int TrimVal=0;
int InitialTrimVal=0;

int LeftLowerTrim=4;  // pin4
int LeftLowerTrimV=LOW;
int LeftLowerTrimVal=0;
int LeftLowerTrimValE=0;

int LowerMap=0;
int UpperMap=0;

void setup(){

WingFoldLeft.attach(5);  //pin5
pinMode(Accept, INPUT);
pinMode(LeftLowerTrim, INPUT);
pinMode(Trims,INPUT);
EEPROM.write(LeftLowerTrimValE,90);  //Use 90 as a starting point

  Serial.begin(9600);
 
}

void loop(){


//TrimVal=map(TrimVal,0,1023,0,1023);

LeftLowerTrimVal=EEPROM.read(LeftLowerTrimValE);
LeftLowerTrimV=digitalRead(LeftLowerTrim);
AcceptVal=digitalRead(Accept);
TrimVal=analogRead(Trims);
WingFoldLeft.write(LeftLowerTrimVal);

Serial.print("trim setup = "); 
Serial.println(LeftLowerTrimV);
Serial.print("Accept = ");
Serial.println(AcceptVal);
Serial.print("TrimVal = ");
Serial.println(TrimVal);
 
while(LeftLowerTrimV==HIGH){
Serial.print("trim setup = ");
Serial.println(LeftLowerTrimV);
Serial.print("Accept = ");
Serial.println(AcceptVal);
Serial.print("TrimVal = ");
Serial.println(TrimVal);
Serial.print("LowerMap = ");
Serial.println(LowerMap);
Serial.print("UpperMap = ");
Serial.println(UpperMap);

AcceptVal=digitalRead(Accept);    //Read the digital input 9 - Accept 
TrimVal=analogRead(Trims);  //Read the trim pot value
LeftLowerTrimVal=EEPROM.read(LeftLowerTrimValE);

WingFoldLeft.write(LeftLowerTrimVal);  //write servo to current lower trim value stored in EEPROM

//Only allow to happen once.
InitialTrimVal=TrimVal; //Setup something to compare values to

delay(500);  //Allow time for trim pot to be adjusted

LowerMap=map(TrimVal, 0,TrimVal, 0, LeftLowerTrimVal);   //Map from 0 to the current trim pot value and current servo location (Lower end)
UpperMap=map(TrimVal, 1023, TrimVal, 90, LeftLowerTrimVal); //Map from 90 to the curretn trim pot value and current servo location (Upper end)

//use the lower map if the initial trim value is larger then the current trim value (pot has been turnd down and input is less)
if (InitialTrimVal>LowerMap){
WingFoldLeft.write(LowerMap);
  if(AcceptVal==HIGH){                                 //Only change LeftLowerTrimVal if accept is pressed
    EEPROM.write(LeftLowerTrimValE, LowerMap); //Stores value in EEPROM so it can be recalled once calibration mode is exited                                 
  }
}

//use the upper map if the initial trim value is less then the current trim value (pot has been turnd up and input is more)
if (InitialTrimVal<LowerMap){
WingFoldLeft.write(UpperMap);
  if(AcceptVal==HIGH){                                 //Only change LeftLowerTrimVal if accept is pressed
    EEPROM.write(LeftLowerTrimValE, UpperMap); //Stores value in EEPROM so it can be recalled once calibration mode is exited                                 
  }
}

LeftLowerTrimV=digitalRead(LeftLowerTrim);                   //Check to see if setup selections conditions have changed
delay(200); //allow time for servo to move to new location
}

delay(500);  //for serial coms
}





UKHeliBob

Your requirements seem quite simple but your code looks complicated.  How about this ?
Code: [Select]
calibrate(servoNumber, endPoint)
  while accept button not pressed
    read pot position
    map pot position to give current position
    move servo(servoNumber) to current position
  end of while
 
  save current position to the eeprom location determined by servoNumber and endPoint

end of function

Create an array of servo objects (search this forum).  Call the calibration routine with a servo number and a variable indicating which endpoint is to be calibrated.

NOTE - the servo will move immediately to the trim position set by the pot when the function is entered.  Do you need to know where the previous trim position was ?  If so, you will need another button to switch between the original position and the new one before it is accepted.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

grantastley

Quote
NOTE - the servo will move immediately to the trim position set by the pot when the function is entered.

Your code is very similar to how mine started out (However I was not using arrays) however then I realised, what if the current position of the pot would set the position of the servo to outside its current trim position when the setup function is entered.  This is not desirable as it could cause the part the servo is controlling to foul on another part and cause damage.  However I still want to be able to set the servo outside its current end point by turning the pot.
So when the function is entered I would like the servo to move to its current end limit no matter what the value of the pot is and then use the pot from it current position to manipulate the servo, setting a new end point.
I realise that this will not give a linear adjustment of the servo depending on where the pot is positioned.  That is if it is closer to its end values, but this could also be used as an advantage giving better resolution in the desired direction by turning the pot all the way to the other direction before the setup is entered then you are able to use the full input range to make an adjustment in just one direction, making fine tuning easier.

The setup also utilises a lcd screen and I have got the old value printed on the screen and also the new position that would be set by the pot.  Maybe if the above method is not possible I would just have another button like you said to move the servo to its new location set by the pot.  This way you will be able to set it to the old position using the information on the screen.

PeterH


If this is not enough detail please let me know.


I'm still not getting what you expect to happen to the pot position and the servo position during this procedure. Until that is clear in your head, it is a waste of time trying to code it.

If you're finding it hard to visualise, try working through an example scenario in your head and write down what you expect to happen in terms of things outside the Arduino.
I only provide help via the forum - please do not contact me for private consultancy.

grantastley

#7
Jul 09, 2013, 02:03 am Last Edit: Jul 09, 2013, 02:07 am by grantastley Reason: 1
It is clear in my head.  

When you enter the setup procedure it does not matter what position the pot is in (analog input) the servo will go to its current end limit stored in the EEPROM

Then when you move the pot from what ever position it is in (change the analog input value) the servo will move, clockwise if the input value increases, anticlockwise if the input value decrease.

Then when you are happy with the new end position press accept to store that value in the EEPROM.

I am nearly there with the following code.  The servo does as expected only problem is when I press accept the servo jumps to another value (momentarily goes to a random position) then goes back to where I set it at using the accept button.  Not sure what is causing this "jump"  
Code: [Select]

#include <Servo.h>  //include servo libery
#include <EEPROM.h> //Allow to read and write to EEPROM

boolean FirstTime;

Servo WingFoldLeft;

int Accept=2;  //pin 2
int AcceptVal=LOW;

int Trims=3;  //analog pin 3
int TrimVal=0;
int InitialTrimVal=0;

int LeftLowerTrim=4;  // pin4
int LeftLowerTrimV=LOW;
int LeftLowerTrimVal=0;
int LeftLowerTrimValE=0;

int LowerMap=0;
int UpperMap=0;

void setup(){

WingFoldLeft.attach(5);  //pin5
pinMode(Accept, INPUT);
pinMode(LeftLowerTrim, INPUT);
pinMode(Trims,INPUT);
EEPROM.write(LeftLowerTrimValE,90);  //Use 90 as a starting point

 Serial.begin(9600);
 
}

void loop(){

FirstTime=true;  //Reset flag, put this inside calibrate while loop.

LeftLowerTrimVal=EEPROM.read(LeftLowerTrimValE);
LeftLowerTrimV=digitalRead(LeftLowerTrim);
AcceptVal=digitalRead(Accept);
TrimVal=analogRead(Trims);
WingFoldLeft.write(LeftLowerTrimVal);

Serial.print("trim setup = ");  
Serial.println(LeftLowerTrimV);
Serial.print("Accept = ");
Serial.println(AcceptVal);
Serial.print("TrimVal = ");
Serial.println(TrimVal);
 
while(LeftLowerTrimV==HIGH){

Serial.print("trim setup = ");
Serial.println(LeftLowerTrimV);
Serial.print("Accept = ");
Serial.println(AcceptVal);
Serial.print("TrimVal = ");
Serial.println(TrimVal);
Serial.print("LowerMap = ");
Serial.println(LowerMap);
Serial.print("UpperMap = ");
Serial.println(UpperMap);

AcceptVal=digitalRead(Accept);    //Read the digital input 9 - Accept  
TrimVal=analogRead(Trims);  //Read the trim pot value
LeftLowerTrimVal=EEPROM.read(LeftLowerTrimValE);
 
 //Only allow to happen once.
 if(FirstTime){
   InitialTrimVal=TrimVal; //Setup something to compare values to
   WingFoldLeft.write(LeftLowerTrimVal);  //write servo to current lower trim value stored in EEPROM
   FirstTime=false;
 }
 
delay(500);  //Allow time for trim pot to be adjusted

LowerMap=map(TrimVal, 0,InitialTrimVal, 0, LeftLowerTrimVal);   //Map from 0 to the current trim pot value and current servo location (Lower end)
UpperMap=map(TrimVal, 1023, InitialTrimVal, 90, LeftLowerTrimVal); //Map from 90 to the curretn trim pot value and current servo location (Upper end)

//use the lower map if the initial trim value is larger then the current trim value (pot has been turnd down and input is less)
if (InitialTrimVal>LowerMap){
WingFoldLeft.write(LowerMap);
}

//use the upper map if the initial trim value is less then the current trim value (pot has been turnd up and input is more)
if (InitialTrimVal<LowerMap){
WingFoldLeft.write(UpperMap);
}

if(AcceptVal==HIGH){
 EEPROM.write(LeftLowerTrimValE, WingFoldLeft.read());  //write new value to EEPROM
}

LeftLowerTrimV=digitalRead(LeftLowerTrim);                   //Check to see if setup selections conditions have changed
delay(200); //allow time for servo to move to new location
}

delay(500);  //for serial coms
}


PeterH

I take it that the value you're adjusting is adjusted by relative movements of the potentiometer and not based on the absolute position. I haven't matched that behaviour up with your code yet, but the procedure you're describing seems reasonable. Given that you seem to be just looking for a glitch in the servo position, I suggest you write a brief trace message to the serial port each time you move the servo during this process. If you include the new servo position in the trace message, you will be able to see which statement is sending it to the spurious position. Then you can look at the code and see whether you expect that piece of code to be executing at that point in the scenario, and where the value is coming from.
I only provide help via the forum - please do not contact me for private consultancy.

grantastley

#9
Jul 09, 2013, 04:21 am Last Edit: Jul 09, 2013, 05:01 am by grantastley Reason: 1
Quote
I take it that the value you're adjusting is adjusted by relative movements of the potentiometer and not based on the absolute position.

Not sure what the difference is here? However the servo moves as the potentiometer is being rotated.

I found the problem.  But first here is the current code I am using.
Everything else works just as I would like :)

Code: [Select]

#include <Servo.h>  //include servo libery
#include <EEPROM.h> //Allow to read and write to EEPROM

boolean FirstTime;

Servo WingFoldLeft;

int Accept=2;  //pin 2
int AcceptVal=LOW;

int Trims=3;  //analog pin 3
int TrimVal=0;
int InitialTrimVal=0;

int LeftLowerTrim=4;  // pin4
int LeftLowerTrimV=LOW;
int LeftLowerTrimVal=0;
int LeftLowerTrimValE=0;

int LowerMap=0;
int UpperMap=0;

boolean FirstLowMap;
boolean FirstUpperMap;

void setup(){

WingFoldLeft.attach(5);  //pin5
pinMode(Accept, INPUT);
pinMode(LeftLowerTrim, INPUT);
pinMode(Trims,INPUT);
EEPROM.write(LeftLowerTrimValE,45);  //Use 90 as a starting point

 Serial.begin(9600);
 
}

void loop(){

FirstTime=true;  //Reset flag, put this inside calibrate while loop.
FirstLowMap=true;
FirstUpperMap=true;

LeftLowerTrimVal=EEPROM.read(LeftLowerTrimValE);
LeftLowerTrimV=digitalRead(LeftLowerTrim);
AcceptVal=digitalRead(Accept);
TrimVal=analogRead(Trims);
WingFoldLeft.write(LeftLowerTrimVal);

Serial.print("trim setup = ");  
Serial.print(LeftLowerTrimV);
Serial.print("Accept = ");
Serial.print(AcceptVal);
Serial.print("TrimVal = ");
Serial.print(TrimVal);
Serial.print("first time = ");
Serial.println(FirstTime);
 
while(LeftLowerTrimV==HIGH){

Serial.print(" trim setup = ");
Serial.print(LeftLowerTrimV);
Serial.print(" Accept = ");
Serial.print(AcceptVal);
Serial.print(" TrimVal = ");
Serial.print(TrimVal);
Serial.print(" LowerMap = ");
Serial.print(LowerMap);
Serial.print(" UpperMap = ");
Serial.print(UpperMap);
Serial.print(" first time = ");
Serial.print(FirstTime);
Serial.print(" Initial trim = ");
Serial.println(InitialTrimVal);

AcceptVal=digitalRead(Accept);    //Read the digital input 9 - Accept  
TrimVal=analogRead(Trims);  //Read the trim pot value
LeftLowerTrimVal=EEPROM.read(LeftLowerTrimValE);
 
 //Only allow to happen once.
 if(FirstTime==true){
   InitialTrimVal=TrimVal; //Setup something to compare values to
   WingFoldLeft.write(LeftLowerTrimVal);  //write servo to current lower trim value stored in EEPROM
   FirstTime=false;
 }
 
//delay(500);  //Allow time for trim pot to be adjusted

LowerMap=map(TrimVal, 0,InitialTrimVal, 0, LeftLowerTrimVal);   //Map from 0 to the current trim pot value and current servo location (Lower end)
LowerMap=constrain(LowerMap, 0, 90);
UpperMap=map(TrimVal, InitialTrimVal, 1023, LeftLowerTrimVal, 90); //Map from 90 to the curretn trim pot value and current servo location (Upper end)
UpperMap=constrain(UpperMap, 0, 90);

//use the lower map if the initial trim value is larger then the current trim value (pot has been turnd down and input is less)
if (InitialTrimVal>TrimVal){  //was >LowerMap
WingFoldLeft.write(LowerMap);
 
 //need to only happen once
 if(FirstLowMap==true){
   if(AcceptVal==HIGH){
     EEPROM.write(LeftLowerTrimValE, LowerMap);
     FirstLowMap==false;
   }
 }
}

//use the upper map if the initial trim value is less then the current trim value (pot has been turnd up and input is more)
if (InitialTrimVal<TrimVal){  //was <LowerMap
WingFoldLeft.write(UpperMap);
 
 //need to only happen once
 if(FirstUpperMap==true){
   if(AcceptVal==HIGH){
     EEPROM.write(LeftLowerTrimValE, UpperMap);
     FirstUpperMap==false;
   }
 }
}
LeftLowerTrimV=digitalRead(LeftLowerTrim);                   //Check to see if setup selections conditions have changed
delay(500); //allow time for servo to move to new location

}

delay(500);  //for serial coms
}


The problem is in this area
Code: [Select]
//need to only happen once
 if(FirstLowMap==true){
   if(AcceptVal==HIGH){
     EEPROM.write(LeftLowerTrimValE, LowerMap);
     FirstLowMap==false;
   }
 }

as LeftLowerTrimVal is just a read of LeftLowerTrimValE and is in the maped value
Code: [Select]
LowerMap=map(TrimVal, 0,InitialTrimVal, 0, LeftLowerTrimVal);   //Map from 0 to the current trim pot value and current servo location (Lower end)
LowerMap=constrain(LowerMap, 0, 90);
UpperMap=map(TrimVal, InitialTrimVal, 1023, LeftLowerTrimVal, 90); //Map from 90 to the curretn trim pot value and current servo location (Upper end)
UpperMap=constrain(UpperMap, 0, 90);

so once it is changed with EEPROM.write(LeftLowerTrimValE, LowerMap); it changes the maped value to either 0 or 90 and causes the servo to "jump" that is why I added the FirstLowMap boolean but it is still not fixing the problem.  I thought this would only write the current value to the EEPROM and then when the code rolls around next time FirstLowMap would be false hence not allowing that code to write to th EEPROM again?

grantastley

found a typo
Code: [Select]
//need to only happen once
 if(FirstUpperMap==true){
   if(AcceptVal==HIGH){
     EEPROM.write(LeftLowerTrimValE, UpperMap);
     FirstUpperMap==false;
   }
 }

changed FirstUpperMap==false; to FirstUpperMap=false;
and now it all works :)
Still have some more final testing to do but all seems good so far.

Thank you for your time :)

grantastley

Had to change
Code: [Select]
if (InitialTrimVal>TrimVal)
to
Code: [Select]
if (InitialTrimVal>TrimVal&&FirstLowMap==true)
and
Code: [Select]
if (InitialTrimVal<TrimVal)
to
Code: [Select]
if (InitialTrimVal<TrimVal&&FirstUpperMap==true)
to stop the servo moving to the newly mapped location straight after the accept button was pressed.  This only allows for the end limit to be changed once.  If it needs to be changed again the the dip switch connected to LeftLowerTrim - pin4 must be toggled.  I can live with this. 
I might add a millis() type timer of X seconds at the start of the while loop just to handle FirstLowMap, FirstUpperMap and InitialTrimVal to reset them back to true and the current trims value so another end point change can be made after X seconds.

grantastley

Code now with millis timer to allow for changing the end point multiple times after TimerVal has passed.

Code: [Select]

/*
need to add
int LowerMap=0;
int UpperMap=0;
boolean FirstLowMap;
boolean FirstUpperMap;
*/

#include <Servo.h>  //include servo libery
#include <EEPROM.h> //Allow to read and write to EEPROM

boolean FirstTime;
boolean FirstAccept;

Servo WingFoldLeft;

unsigned long Timer;
unsigned long PreviousTimerVal;
const unsigned long TimerVal=3000;  //3 seconds

int Accept=2;  //pin 2
int AcceptVal=LOW;

int Trims=3;  //analog pin 3
int TrimVal=0;
int InitialTrimVal=0;

int LeftLowerTrim=4;  // pin4
int LeftLowerTrimV=LOW;
int LeftLowerTrimVal=0;
int LeftLowerTrimValE=0;

int LowerMap=0;
int UpperMap=0;

boolean FirstLowMap;
boolean FirstUpperMap;

void setup(){

WingFoldLeft.attach(5);  //pin5
pinMode(Accept, INPUT);
pinMode(LeftLowerTrim, INPUT);
pinMode(Trims,INPUT);
//EEPROM.write(LeftLowerTrimValE,45);  //Use 90 as a starting point

  Serial.begin(9600);
 
}

void loop(){
Timer=millis();
 
FirstTime=true;  //Reset flag, put this inside calibrate while loop.
FirstLowMap=true;
FirstUpperMap=true;

LeftLowerTrimVal=EEPROM.read(LeftLowerTrimValE);
LeftLowerTrimV=digitalRead(LeftLowerTrim);
AcceptVal=digitalRead(Accept);
TrimVal=analogRead(Trims);
WingFoldLeft.write(LeftLowerTrimVal);

Serial.print("trim setup = "); 
Serial.print(LeftLowerTrimV);
Serial.print("Accept = ");
Serial.print(AcceptVal);
Serial.print("TrimVal = ");
Serial.print(TrimVal);
Serial.print("first time = ");
Serial.println(FirstTime);
 
while(LeftLowerTrimV==HIGH){
 
Serial.print(" trim setup = ");
Serial.print(LeftLowerTrimV);
Serial.print(" Accept = ");
Serial.print(AcceptVal);
Serial.print(" TrimVal = ");
Serial.print(TrimVal);
Serial.print(" LowerMap = ");
Serial.print(LowerMap);
Serial.print(" UpperMap = ");
Serial.print(UpperMap);
Serial.print(" first time = ");
Serial.print(FirstTime);
Serial.print(" Initial trim = ");
Serial.println(InitialTrimVal);

//Timer 
if((millis()-Timer)>=TimerVal){   //reset timer once accept is pressed (Timer=milis())
  if(FirstAccept==true){
    FirstLowMap=true;
    FirstUpperMap=true;
    InitialTrimVal=TrimVal; //Setup something to compare values to
    WingFoldLeft.write(LeftLowerTrimVal);  //write servo to current lower trim value stored in EEPROM
    FirstAccept=false;  //reset accept first when accept is pressed.
  }
}

AcceptVal=digitalRead(Accept);    //Read the digital input 9 - Accept 
TrimVal=analogRead(Trims);  //Read the trim pot value
LeftLowerTrimVal=EEPROM.read(LeftLowerTrimValE);
 
  //Only allow to happen once.
  if(FirstTime==true){
    InitialTrimVal=TrimVal; //Setup something to compare values to
    WingFoldLeft.write(LeftLowerTrimVal);  //write servo to current lower trim value stored in EEPROM
    FirstTime=false;
  }

LowerMap=map(TrimVal, 0,InitialTrimVal, 0, LeftLowerTrimVal);   //Map from 0 to the current trim pot value and current servo location (Lower end)
LowerMap=constrain(LowerMap, 0, 90);
UpperMap=map(TrimVal, InitialTrimVal, 1023, LeftLowerTrimVal, 90); //Map from 90 to the curretn trim pot value and current servo location (Upper end)
UpperMap=constrain(UpperMap, 0, 90);

//use the lower map if the initial trim value is larger then the current trim value (pot has been turnd down and input is less)
if (InitialTrimVal>TrimVal&&FirstLowMap==true){  //Added firstlowmap //was >LowerMap
WingFoldLeft.write(LowerMap);
 
  //need to only happen once
  if(FirstLowMap==true){
    if(AcceptVal==HIGH){
      EEPROM.write(LeftLowerTrimValE, LowerMap);
      FirstLowMap=false;
      FirstAccept=true;
      Timer=millis();
    }
  }
}

//use the upper map if the initial trim value is less then the current trim value (pot has been turnd up and input is more)
if (InitialTrimVal<TrimVal&&FirstUpperMap==true){  //was <LowerMap
WingFoldLeft.write(UpperMap);
 
  //need to only happen once
  if(FirstUpperMap==true){
    if(AcceptVal==HIGH){
      EEPROM.write(LeftLowerTrimValE, UpperMap);
      FirstUpperMap=false;
      FirstAccept=true;
      Timer=millis();
    }
  }
}
LeftLowerTrimV=digitalRead(LeftLowerTrim);                   //Check to see if setup selections conditions have changed
delay(500); //allow time for servo to move to new location
}
delay(500);  //for serial coms
}


Now just to tidy everything up.

UKHeliBob

I am glad that you got it working the way that you want.

You have 12 servos, each with 2 end points to adjust.  Your current code has variables with very specific names relating to the servos.  Are you going to repeat the code for each servo or is your aim to turn the calibration routine into a function such that it can be used to calibrate either end point of any servo ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

grantastley

#14
Jul 09, 2013, 11:02 am Last Edit: Jul 09, 2013, 11:04 am by grantastley Reason: 1
At the moment I have everything in a calibrate function with each servo having its own code for each end point as above.  However I am interested in seeing if I can condense it somewhat.  Maybe arrays as you were saying before would work.

Quote
turn the calibration routine into a function such that it can be used to calibrate either end point of any servo ?

This would be ideal if I can figure it out.

At the moment because of limited IO (even though I am using the mega 2560) the servo setups are  as follows.  With each area (WingFold, etc) having a dipswitch to select it and change the name of the input from CommonTrim1 to LeftGearDoorLowerTrim for example.  This allows all 34 trims to be set using only 14 inputs (8 + 6).
       
        Common
PIN   Trim Name       LandingGear1              LandingGear2             WingFolding           OilCoolers              Engine              Canopy
22 ComminTrim1  LeftGearDoorLowerTrim  TailGearLowerTrim       LeftLowerTrim     LeftOilLowerTrim    ChokeLowerTrim   CanopyLowerTrim
23 CommonTrim2 LeftGearDoorUpperTrim  TailGearUpperTrim       LeftUpperTrim     LeftOilUpperTrim    ChokeUpperTrim   CanopyUpperTrim
24 CommonTrim3 RightGearDoorLowerTrim SetStaggerDelayDoors   RightLowerTrim     RightOilLowerTrim   ImobLowerTrim   
25 CommonTrim4 RightGearDoorUpperTrim SetStaggerDelayGear    RightUpperTrim     RightOilUpperTrim   ImobUpperTrim   
26 CommonTrim5 TailGearDoorUpperTrim   BrakeLowerTrim       WingLockLowerTrim   CowlLowertrim      
27 CommonTrim6 TailGearDoorLowerTrim   BrakeUpperTrim       WingLockUpperTrim   CowlUpperTrim      
28 CommonTrim7 LeftGearLowerTrim                                       SetFoldSpeed         
29 CommonTrim8 LeftGearUppertrim                                       SetStaggerDelay   

So each of the above have a their own variables - XXXXXTrim, XXXXXXTrimVal, XXXXXXTrimValE.
While variables - FirstLowMap, FirstUpperMap, UpperMap, LowMap, AcceptVal, Accept, firstAccept,  InitialTrimVal, TrimVal, Trims and FirstTime can all be used in each setup as their values are set upon entering the setup.
So I am not quite sure atm how to go about condensing the code but it is something I will work on.

I would be very grateful if you have any suggestions or ideas?      

Go Up