Transition between two different values

I need to make a transition between two different values and get all the numbers in between. For example: 2 transitioning to 4 in 5 seconds -- (2, 2.5, 3, 3.5 ,4) but with more detail. Is there any way I can do this? And this is for an Arduino project, if that helps.

I want the "FixCoordinates()" to transition whenever I change the value.


#include <VarSpeedServo.h>

VarSpeedServo ServoS_1; // Joint at base
VarSpeedServo ServoS_2; // Elbow between a and b

float Sped1;
float Sped2;
// Servo Angles
float ServoS_1_Angle = 180;
float ServoS_2_Angle = 180;

// Define arm Constants
const float a = 17; // lower joint length (cm)
const float b = 21; // upper joint length (cm)

// Correction factors to align servo values with their respective axis
const float S_1_CorrectionFactor = -10; // Align arm "a" with the horizontal when at 0 degrees
const float S_2_CorrectionFactor = -0; // Align arm "b" with arm "a" when at 0 degrees

// Correction factor to shift origin out to edge of the mount
const float X_CorrectionFactor = 0; // X direction correction factor (cm)
const float Y_CorrectionFactor = 0; // Y direction correction factor (cm)

// Angle Variables
float A; //Angle oppposite side a (between b and c)
float B; //Angle oppposite side b
float C; //Angle oppposite side c
float theta; //Angle formed between line from origin to (x,y) and the horizontal

// Distance variables
float x; // x position (cm)
float y; // y position (cm)
float c; // Hypotenuse legngth in cm
const float pi = M_PI; //Store pi in a less annoying format

//===================================================================================

void setup()
{
ServoS_1.attach(11); // Attach servos
ServoS_2.attach(3);
Serial.begin(9600); // -For debuggingx
}
//--------------------------------------------------------------


void loop()
{

if(Serial.available()) {
char val = Serial.read();

if(val == 'r'){
FixCoordinates(12, 0);

}
if(val == 'c'){
FixCoordinates(12, 20);

}
if(val == 's'){
FixCoordinates(12, 30);

}


}
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (25.0 / 1023.0);
// print out the value you read:

Serial.println(voltage);
Serial.print("\t");
// Enter coordinates of point.
CalculateServoAngles(); // Calculate necessary angles of servos
MoveArm(); // Move arm to new position
delay(15);
}

//====================================================================================

// Get x and y measured from the bottom of the base. Function corrects for offset
void FixCoordinates(float x_input, float y_input)
{
x = x_input + X_CorrectionFactor;
y = y_input + Y_CorrectionFactor;
}

// Calculate necessary servo angles to move arm to desired points
void CalculateServoAngles()
{
c = sqrt( sq(x) + sq(y) ); // pythagorean theorem
B = (acos( (sq(b) - sq(a) - sq(c))/(-2*a*c) )) * (180/pi); // Law of cosines: Angle opposite upper arm section
C = (acos( (sq(c) - sq(b) - sq(a))/(-2*a*b) )) * (180/pi); // Law of cosines: Angle opposite hypotenuse
theta = (asin( y / c )) * (180/pi); // Solve for theta to correct for lower joint's impact on upper joint's angle
ServoS_1_Angle = B + theta + S_1_CorrectionFactor; // Find necessary angle. Add Correction
ServoS_2_Angle = C + S_2_CorrectionFactor; // Find neceesary angle. Add Correction

}

// Update the servos
void MoveArm()
{
ServoS_1.write(ServoS_1_Angle, 50); // Move joint to desired position
ServoS_2.write(ServoS_2_Angle, 50); // Move joint to desired position

Serial.print("\t");
Serial.print(x);


}
X transitioning to Y in Z states
1
2
3
4
5
6
distance = Y - X;
step = distance / (Z-1);
for ( int state=0; state < Z; ++state ) {
  pos = X + state*step;
  // use pos
}

Whatever you do, you don't want (nor will you be able to achieve) instant acceleration at one end, and instance deceleration at the other. You'll just end up breaking stuff.

You want a nice smooth start, moving quickly in the middle, and coming gradually to a halt at the end.
https://en.wikipedia.org/wiki/Sine_wave
How can I turn it into a sine wave then?
Actually, the easiest part to use (and visualise) is the cosine from π to 2π
https://en.wikipedia.org/wiki/Sine_wave
Starts off slow, rising quickly in the middle, then slowing down towards the end.

This is how you might calculate it over a unit distance.
1
2
3
4
5
6
7
8
9
10
11
12
int main() {
  double delta = 0.01;
  double distance = 0;
  double prevx = 0.0;
  for ( double theta = M_PI ; theta < (2*M_PI) ; theta += delta ) {
    double x = (cos(theta)+1)/2;
    double dx = x - prevx;
    prevx = x;
    distance += dx;
    printf("Move=%.3f, distance=%.3f\n", dx, distance);
  }
}


First 10
Move=0.000, distance=0.000
Move=0.000, distance=0.000
Move=0.000, distance=0.000
Move=0.000, distance=0.000
Move=0.000, distance=0.000
Move=0.000, distance=0.001
Move=0.000, distance=0.001
Move=0.000, distance=0.001
Move=0.000, distance=0.002
Move=0.000, distance=0.002

Middle 10
Move=0.005, distance=0.475
Move=0.005, distance=0.480
Move=0.005, distance=0.485
Move=0.005, distance=0.490
Move=0.005, distance=0.495
Move=0.005, distance=0.500
Move=0.005, distance=0.505
Move=0.005, distance=0.510
Move=0.005, distance=0.515
Move=0.005, distance=0.520

Last 10
Move=0.000, distance=0.998
Move=0.000, distance=0.998
Move=0.000, distance=0.999
Move=0.000, distance=0.999
Move=0.000, distance=0.999
Move=0.000, distance=1.000
Move=0.000, distance=1.000
Move=0.000, distance=1.000
Move=0.000, distance=1.000
Move=0.000, distance=1.000

Topic archived. No new replies allowed.