This sketch contains a function softCurve which, given a value between 0 and 1 returns another value between 0 and 1 that has a "soft" start and end.
The logistical curve is infinitely differentiable, and so the speed, the acceleration, the jerk, and derivatives beyond that all have non-infinite values. The curve is, however, infinitely long. To accommodate that, this sketch clips the curve at -3 and 4. Some experimentation may be required, depending on your application.
#include <Servo.h> Servo s; const uint32_t SPEED = 1000; const int target[] = { 10, 60, 170, 90 }; const int targets = sizeof(target) / sizeof(*target); uint32_t pollMs; uint32_t startMs; int whichTarget = 0; void setup() { s.attach(6); pinMode(LED_BUILTIN, OUTPUT); s.write(target[0]); delay(SPEED); startMs = millis(); digitalWrite(LED_BUILTIN, HIGH); } void loop() { if (millis() == pollMs) return; pollMs = millis(); uint32_t ms = millis(); if (ms - startMs >= SPEED) { digitalWrite(LED_BUILTIN, LOW); delay(SPEED); digitalWrite(LED_BUILTIN, HIGH); whichTarget = (whichTarget + 1) % targets; startMs = ms = millis(); } const int a = target[whichTarget]; const int b = target[(whichTarget + 1) % targets]; s.write( softCurve((ms - startMs) / (double)SPEED) * (b - a) + a ); } // SOFT CURVE implementation #define LOGISTICAL(x) (exp(x)/(exp(x)+1)) double logistical(double x) { double y = exp(x); return y / (y + 1); } // pecomputed constants // I make the start of the movement a little more jerky than the end // making these values larger makes the start and end of the range of movement // softer, at the price of the servo needing to move more quickly towards // the center of its motion. const double STARTING_X = -3; const double ENDING_X = 4; const double STARTING_Y = LOGISTICAL(STARTING_X); const double ENDING_Y = LOGISTICAL(ENDING_X); /* * Compute a curve with a soft acelleration and decelleration, and less jerk * @param amt a value between 0 and 1, 0 being the start of the soft motion, 1 the end * @return a value between 0 and 1. Do arithmetic to get the range you want. */ double softCurve(double amt) { double x = STARTING_X + amt * (ENDING_X - STARTING_X); double y = logistical(x); // convert to a 0-1 value, y = (y - STARTING_Y) / (ENDING_Y - STARTING_Y); return y; }