Position feedback for servo motor not correct

Hello,

I would like to control the position (angle) of my servo motor. When I ask it to turn 90 degrees for example, the motor does it correctly but the feedback that appears is wrong. It shows me 45.48 degrees. What is wrong with my code ?


#include <Servo.h>

Servo myservo;  

float servoAnaloglnPin=A1;  


const int servoPin = 2; 

const int servoAnalogOut = A0; 
unsigned int servoValue0Deg;
unsigned int servoValue330Deg;

int voltage_of_servo; 
float voltage;  
float current;  

float voltage_of_servo_1;
float voltage_of_servo_2;

int position_feedback_angle;


void setup() {

    myservo.attach(servoPin);
    Serial.begin(9600);
    calibration();

}


void loop() {
  if (Serial.available()){ 
    int angle = Serial.parseInt();  
    if (Serial.read() == '\n'){   
      
      Serial.print("-Desired position (degree) : ");
      Serial.println(angle);/
      angle = map(angle, 0, 360, 0, 190); // Mapea el ángulo de 0-360 a 0-190
      myservo.write(angle); // Mueve el servomotor al ángulo especificado     
      

      delay(150);                       // waits 15 ms for the servo to reach the position

     


      voltage_of_servo = analogRead(servoAnaloglnPin); 
      Serial.print("Analog voltage: ");
      Serial.println(voltage_of_servo);

      //float voltage = map(voltage_of_servo, 0, 1023, servoValue0Deg, servoValue180Deg); // Rescale to potentiometer's voltage (from 0V to 8.4V): même chose que en bas
      voltage = 7.4*(voltage_of_servo)/1023; //Ajout Ikram 1023 au lieu de servoValue330Deg
      
      
      //Serial.print("Analog A0: ");
      //Serial.println(analogRead(servoAnalogOut));

      Serial.print(" -volatge (V):"); 
      Serial.println(voltage);

      current = voltage/1.6; //I=V/R, resister is 1.6 ohm 
      Serial.print(" -CURRENT (ohm):"); 
      Serial.println(current);

      delay(150);

      float position_feedback_angle = ((voltage * 330)/ 7.4); 

      Serial.print("-Feedback position (degree): ");
      Serial.println(position_feedback_angle);  

        }
  }
}

 
void calibration() {
  myservo.write(0); //set the servo to 0 position 
  delay(500); //wait for the servo to reach there 
  servoValue0Deg= analogRead(servoAnalogOut); // Pot value at 0 degrees
  Serial.println("Pot value for 0 deg is " + String(servoValue0Deg)); // Print it! //
  voltage_of_servo_1 = 7.4*(servoValue0Deg)/1023;
  Serial.println(voltage_of_servo_1); //It does what it says 

  delay(1000); //fancy delay 
  myservo.write(180); //go to 180 degrees 
  delay(500); //wait for the servo to reach there 
  servoValue330Deg= analogRead(servoAnalogOut); //pot value at 180 deg 
  Serial.println("Pot value for 330 deg is " + String(servoValue330Deg)); 
  voltage_of_servo_2 = 7.4*(servoValue330Deg)/1023;
  Serial.println(voltage_of_servo_2); //It does what it says 


  Serial.println("Now going to 0 Degrees"); //It does what it says 
  myservo.write(0);// going to 90 degrees 
  delay(1000);// wait for it to reach there 
  }


Could it be that your reading for 330 degrees was taken when the servo was at 180 degrees?

HI @Delta_G,

the code in total is a little bit confusing:

  • The calibration takes its data from analogRead(servoAnalogOut)
  • It is based on 330 degree (as in loop() ) but moves only 180 degrees.
  • The data calculated in calibration are only printed but are not used in loop ...
  • In loop() the voltage level is taken from analogRead(servoAnaloglnPin) and the position_feedback_angle is calculated from ((voltage * 330)/ 7.4);

And then the angle input is mapped ...

      Serial.print("-Desired position (degree) : ");
      Serial.println(angle);
      angle = map(angle, 0, 360, 0, 190); // Mapea el ángulo de 0-360 a 0-190
      myservo.write(angle); // Mueve el servomotor al ángulo especificado     

If you input 90 ---> you get something around 47 ...

@ikraduino:

Did you get the code from someone else and made changes?
ec2021

Your topic has been moved. Please do not post in "Uncategorized"; see the sticky topics in https://forum.arduino.cc/c/using-arduino/uncategorized/184.

As already noted you are not using the calibration values you saved.

You should use something like this:

position_feedback_angle = map(voltage_of_servo, servoValue0Deg, servoValue330Deg, 0, 330);

map returns a longint ( if you need a float you can define an fmap function modifying the original one )

Only a note, you are using variable names in an 'inconsistent way', I mean you are using variable 'voltage_of_servo' ( which is not a voltage, but the result of a/d conversion ) and then 'voltage_of_servo_2' ( which is a voltage ), the conversion of 'servoValue330Deg' ( I'm telling you this... as I'm doing this too sometimes, we use to say 'siamo nella stessa barca' ; - )

Hi, @ikraduino

What servo are you using?
Can you please post a link to data/specs of the servo.

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

What model Arduino are you using?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia: