Un smooth motion using swiftecx25

Hi all,

Newbie/wannabee arduino tinkerer here. Im working on an analog vario gauge for a glider. Im using a x27.168 stepper from adafruit, that (for now), I connected straight to an arduino uno. Im using the SwitecX25 library.

The signal comes from an openvario glider computer, and is basically a number with 2 decimals precision, that represents climb/sink rate in meter per second, and Im only interested in values between -5.00 and +5.00.

I got it working, but I would like to smooth the motion. Have a look:

It looks better on video than it does to my eye, but especially with small movements, I think its still too jerky, and Im at a loss on how to improve it.

I tried adjusting the range, so I would more steps per meter/s, but it makes no real difference (by sheer luck, 945 steps of this motor is pretty close to the number of values between -5.00 and +5.00).

Here is my code:

#include "SwitecX25.h"

//setup stepper
#define STEPS (315*3) // standard X25.168 range 315 degrees at 1/3 degree steps
SwitecX25 motor1(STEPS,2,3,5,13);

int target=0;
int ind1; 
int ind2;
int ind3;
int ind4;
int ind5;
String received;
String msgtype;
String variot;
float vario;

void setup() {
  // run the motor against the stops

void loop()
  static char buffer[80];
  if (readline(Serial.read(), buffer, 80) > 0) {  
    if (received.substring(0,4) == "$POV"){
 //     Serial.print("got vario:> "); 
        ind1 = received.indexOf(',');  //finds location of first ,
        ind2 = received.indexOf(',', ind1+1 );   //Position of P or E or V
        msgtype = received.substring(ind1+1, ind2);   //P or E or V
     // Serial.println(msgtype);
        if (msgtype == "E") { // vario message
          ind3 = received.indexOf(',', ind2+1 ); //value
          variot= received.substring(ind2+1, received.length()); //IAS
          ind4= variot.indexOf('*'); //position of checksum data at end
          variot= variot.substring(0,ind4); //strip checksumdata
          //  Serial.println(vario);

int readline(int readch, char *buffer, int len)
  static int pos = 0;
  int rpos;

  if (readch > 0) {
    switch (readch) {
      case '\n': // Ignore new-lines
      case '\r': // Return on CR
        rpos = pos;
        pos = 0;  // Reset position index ready for next time
        return rpos;
        if (pos < len-1) {
          buffer[pos++] = readch;
          buffer[pos] = 0;
  // No end of line has been found, so return -1.
  return -1;

Is there something in can do in code to make this smoother? Would a stepper controller with microstepping help?

Also, Im a little surprised how noisy this stepper is. Its probably acceptable in a glider, but certainly not a car, which is where these are typically used. Is this normal?

I appreciate any and all help I can get with this.

It seems to be following the GPS unit's graph accurately. You want it to be better than the data going into it?

Perhaps you just want to low-pass filter the data?

Thanks for the suggestion. TBH, Im not entirely sure what the problem is, but I quickly added an extreme low pass filter to see if that is the problem. Its not. Have a look and keep a close eye on the tip of the needle:

When movements are large and fast, all is well. But when movements are small, you can clearly see it "step" from one position to the next. I guess the speed should be reduced for small movements, somehow?

You were somehow imagining that a "stepper motor" doesn't move in steps?

You could try driving it with a proper stepper driver such as an A4988 which has micro-stepping. It should be possible to adjust the current limit down far enough.

This type of stepper is used in a tens of million of automotive gauges. Ive never seen a needle in a car instrument jerk like that. Of course it has a finite number of steps, but I dont think thats the real issue. I think the problem is that when the values fluctuate between two steps, the stepper bounces between those steps accelerating and decelerating way too fast, so you get jerks like the seconds hand of an analog clock. If that same movement was done much slower, Im pretty sure it would look smooth.

Microstepping may hide the issue, provided it works, but I really think this can be solved in software.

Normally the pointer would be much lighter - the 3D printed one is heavy and vibrating at visible
frequencies as a result. Some mechanical damping might also help

The printed needle is actually lighter than the one that was included with the stepper. But admittedly, its mass distribution is different, which is more important here. Still, I attached the "stock" needle, and this is what that looks like:

Its just as bad.

As for mechanical damping; not sure how I would go about doing that, but really, that shouldnt be necessary?

Write a quick sketch to see what is happening. No GPS input. Just single step with a half second delay between. 20 steps up. 20 steps down. Can you see the steps here?

Yes, that’s not oscillating any more (your needle had a much higher MoI I suspect).

You won’t get better than that with a stepper dial like this. No-one would notice in practice!

Yes, that's not oscillating any more (your needle had a much higher MoI I suspect).

You won't get better than that with a stepper dial like this. No-one would notice in practice!

Its quite noticeable. Have a look at this:

Would you be happy if that was in your car? I wouldnt. He's using the same setup as me, and is having the same problem. Its easier to see in his setup because the needles are longer.

Ive been reading some more; in automotive gauges they use these exact same stepper motors but with a microstepping controller:

One problem seems to be finding them, in quantities of less than 100 and with a breakout board.

As luck would have it, I found that I did have a polulu A4988 laying around. I tried with that, feeding the motor 9V (its specced for 5-10V). I used this driver:

Movement is somewhat erratic though, especially when doing microstepping. Maybe I just need to adjust some values, not sure. Another problem is that I dont see how I can do non blocking moves with that library.

That video shows very different behaviour to the previous ones.

Have you tried just generating a linear ramp? I suspect your signal source is scratchy/noisy and
you are seeing that source noise correctly mimiced by the stepper.

This is the sort of response these motors can give if driven appropriately:

This is the sort of response these motors can give if driven appropriately:

Arduino + Switec X25.168 stepper analog gauge - YouTube

Straight, linear movements. Mine can do that similarly. But what it cant do, is this:

Same stepper, but using microstepping controller designed for those steppers. I ordered one, along with a SOP28 socket. Hopefully that will cure it.