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
// 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
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
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.
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.