Switec X27-168 stepper zeroing subroutine

Hi all, I am using the Switec X27-168 stepper motor in order to output a gauge in a flight sim game. I have used programs using EasyDriver an A4988 stepper driver boards for a while, but found the EasyDrivers to be very fragile, plus the driver boards required a 12v power supply when the X27 steppers function with very low voltages and power.

As part of the ongoing process, i ended up trying to run the X27 steppers direct from 4 pins of an Arduino nano, and to my amazement I found that not only did it work, but It seemed to be more reliable and when using an RS485 connection was more stable and easier to get working. As a result I have continued to experiment with them woking directly from a Nano. I had three gauges all being displayed simultaneously from one Nano with no lag, perfectly reliably, and after months of use they still work fine.

Now, this is going to be contentions, because every post I've read says to use a stepper driver, for a number of reasons, not least because there may be back EMF or drive..... ok, that may be the case, but my experience has been extremely positive using direct control. I therefore ask for patience (tolerance?) and for you to suspend your impulse to direct me back to a driver board, and help me find a solution to one of the niggles that is a result of abandoning the 'old' thinking.

The issue concerns the fact that if you discontinue the game without essentially parking everything and so restoring the gauges to their Zero positions, they will logically start the next session with 'zero' being the point at which they were last depowered. The guys who set up the commonly used sketches that work via driver boards have such a zeroing subroutine in their sketches, where the stepper is commanded to move 101% positive rotation ( which as the X27 stepper has a stop means it will rotate and stall aginst the positive stop) then command exactly the same in the negative direction, zeroing the stepper. I as an engineer don't understand the need for the first part as logically (for me at least) 101% negative will always take you to min position, but maybe there is an electronic reason.

So what I would like is to have a zeroing routine for the steppers. Looking at the sketch which was derived from one pulled from an old site, it looks like there's some code in there to attempt to do so, but it doesn't seem to do anything.

I have tried lines in the sketch in the setup to say
setPosition (currentPosition-900);
Motor1.update

and similar. It compiles fine, but does nothing

Can I therefore ask for advice on codes to try and achieve a zeroing function for this? I understand that probably none of you have the DCS world game that this functions with, but maybe you have access to an X27 stepper to play with!

If it comes to nothing I have lost nothing but I would really appreciate any guidance

Thanks

Les

#define DCSBIOS_DEFAULT_SERIAL
 #include "DcsBios.h"
 #include "SwitecX25.h" 

// 315 degrees of range = 315x3 steps = 945 steps int newValue; 
unsigned int maxSteps = 800; // declare motor1 with 945 steps on pins 

SwitecX25 motor1(maxSteps, 6, 5, 7, 8); 
void setup(void) 
{
 DcsBios::setup(); motor1.zero(); // this is a slow, blocking operation motor1.setPosition(500); 
}
 void onApuTempChange(unsigned int newValue) 
{
 unsigned int position = map(newValue, 0, 65535, 0, maxSteps);

 motor1.setPosition(position);
 }
 DcsBios::IntegerBuffer apuTempBuffer(0x10c0, 0xffff, 0, onApuTempChange);

 void loop(void)
 {
 motor1.update(); 
DcsBios::loop(); }

Just (over)drive it to the zero stop on startup, as suggested. I also see no need to drive it to the maximum end stop, unless it is intended as a visual check that the full swing can even be achieved.

So I tried that, but it doesn't happen; I'm not clear why, seems a simple instruction but something stops the instruction from being carried out.

Is the syntax wrong? Should the instruction be in setup, or a run once only loop?

Les

If you are saying that the following does nothing, then study the library code to see why.

void setup(void) 
{
 DcsBios::setup(); motor1.zero(); 
}

If your shaft has a flat spot, can't you just use that for a limit switch to activate on the flat spot?

Concerning driving these steppers direct from the processor pins, I don't think there will be a problem. These little steppers are I believe based on a similar principle to the "Lavet" motors used in quartz clocks and watches, though the design can go backwards as well as forwards. I drive the stepper in an old quartz movement in one of my clocks using a 220R series resistor but no flywheel diodes and I know of designs that don't even have the series resistor. The current needed for the coil is very low and they have quite high resistance. Inductance is also low so not much energy needs to be dissipated when the current switches off. I think CMOS processes as used in the Arduino have reverse biased diodes to each rail on the pins anyway and these seem to happily prevent damage from the inductive kick. My dial gets impulsed every second, 86400 times a day, 31 million times a year, and it has been going for 2 years at least without failing.

I took a look at the .cpp file and saw that the timing was set for the zeroing funtion to 500 ms so I increased that to 2000 to see what it would do. It only seemed to let the stepper move randomly for a couple of seconds.

I was puzzled as to why I couldn't get the argument Motor1.setPosition (value) to work but then saw that one of the variables in the .h file was targetStep.

I added the line

 unsigned int targetStep = -800 

and then changed the setup line to

motor1.setPosition(targetStep);
motor1.update();

That then moves the pointer full scale anti-clockwise on power up.

It's academic now, but still curious to know why I couldn't just define setPosition as a value

Les

The zeroing is working a bit too well, it seems to be affecting the steady state operation of the 'gauge' as it gradually moves the pointer towards the zero position when the gauge should be steady. I think there needs to be something to make the zeroing a run once function, and I need to work out how to do that

Les

Can I ask you experts out there to comment on why the inclusion of the zeroing in the void setup should affect the steady state running? My understanding is that anything that is not in the void loop part will be run once and then ignored. However by commenting out the

 motor1.zero();  // this is a slow, blocking operation
  motor1.setPosition(targetStep);
  motor1.update();

the gauge will not zero but it also is rock solid after and hold the gauge correct position. This is the complete sketch

#define DCSBIOS_DEFAULT_SERIAL

//#define DCSBIOS_RS485_SLAVE 34

//#define TXENABLE_PIN 2

#include "DcsBios.h"
#include "SwitecX25.h"

// 315 degrees of range = 315x3 steps = 945 steps
int newValue;
unsigned int maxSteps = 800;
unsigned int targetStep = -800;
unsigned int currentStep;


// declare motor1 with 945 steps on pins 8-11
//SwitecX25 motor1(maxSteps, 9, 8, 10, 11);
SwitecX25 motor1(maxSteps, 5, 4, 6, 7);



void setup(void) {

  DcsBios::setup();

  motor1.zero();  // this is a slow, blocking operation
  motor1.setPosition(targetStep);
  motor1.update();

}



void onApuRpmChange(unsigned int newValue) {
  unsigned int position = map(newValue, 0, 65535, 0, maxSteps);
  motor1.setPosition(position);
}
DcsBios::IntegerBuffer apuRpmBuffer(0x10be, 0xffff, 0, onApuRpmChange);


void loop(void) {

  motor1.update();

  
  DcsBios::loop();
}

Cheers

Les

It can't. The setup function runs once only at startup. There must be something wrong with the code in the loop function, or the hardware.

What is this line supposed to do, outside of any function?

DcsBios::IntegerBuffer apuRpmBuffer(0x10be, 0xffff, 0, onApuRpmChange);

Essentially it is the line that defines the "address" of the data that the game outputs that the sketch is using to define where the stepper is moved to. DCS BIOS is an add on for the DCS World flight sim that allows extenal hardware to be connected to the game and function as input / output / display devices. All the sketches that use the DCS BIOS system use a standard set of code to define the data needed, for example this is for the Right engine hydraulic gauge

Right Hydraulic PressureA-10C/R_HYD_PRESS
Output Type: integer Address: 0x10c4 Mask: 0xffff Shift By: 0 Max. Value: 65535 Description: gauge position
void onRHydPressChange(unsigned int newValue) {
    /* your code here */
}
DcsBios::IntegerBuffer rHydPressBuffer(0x10c4, 0xffff, 0, onRHydPressChange);
DcsBios::ServoOutput rHydPress(0x10c4, PIN, 544, 2400);

Depending on the type it can be an output for an LCD, OLED, LED, stepper / servo, or an input for a switch, encoder or potentiometer

So it is puzzling that removal of the zeroing code results in the "gauge" behaving itself, other than the fact it won't zero at the beginning

Les

Hi Les, i made a gauge and like code for this can you help me to get it to work on dcs? Can you contact me in a private massage.. this is my gauge..

Hi Dutch, sorry for the late reply

Happy to help, I suggest that you go to the DCS 'home cockpit' forum, I and the other like minded guys will definitely help you

Cheers

Les

There is a dedicated chip for these that works without any library - one pin sets the direction and the other you pulse for the number of steps . Can’t recall the chip no tho as it was a couple of yrs back .

The dedicated chip is a AX1201728SG a quad driver for exactly this kind of automotive type stepper.

Allegedly STI6606 is also a functional driver as is VID6606

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.