Jump to content

Stepper x27 and DCS Bios request


Johan4668

Recommended Posts

17 hours ago, Vinc_Vega said:

Hi Johan,

try another Nano, maybe there is something broken within the communication chipset.

Regards, Vinc

Done a test.. the 0 km - 13 is working the other way how can I reverse that? And I need some code to make the 0 - 1000 meter work.. with 0 position.. 

Then I need to calibrating the whole thing... 

I upload what it is doing now..

Link to comment
Share on other sites

On 3/12/2023 at 9:14 PM, Vinc_Vega said:

No, for the standard USB mode just leave it as it is.

For the RS485 option (later) delete the first two slashes.

As you may see, I connected the encoder to pins D3 and D4 and the stepper for the km-disk to pins D5 to D8.

Regards, Vinc

How can you change the direction of the stepper? 

Link to comment
Share on other sites

1 hour ago, Johan4668 said:

How can you change the direction of the stepper? 

I'll give you a tested answer when I'm home tonight.

 

Regards, Vinc

  • Thanks 1

Regards, Vinc

real life: Royal Bavarian Airforce

online: VJS-GermanKnights.de

[sIGPIC][/sIGPIC]

Link to comment
Share on other sites

23 hours ago, Johan4668 said:

How can you change the direction of the stepper? 

Hi Johan

I reproduced the behavior of your stepper. It has been working good with the A-10C gauges but moves strange with the Bf-109.

No idea what happens, but I'll do further investigation at the weekend.

 

The Stepper direction may be chagend in different ways:

1) Quick and dirty by flipping the mapping interval.

just change the last two values from 

int stepperPosition = map(newValue, 0, 65535, 0, 1260);

to 

int stepperPosition = map(newValue, 0, 65535, 1260, 0);

 

2) Changing the pin order by software

just change the pins pairwise from

AccelStepper stepper0(AccelStepper::HALF4WIRE , 5, 6, 8, 7);

to 

AccelStepper stepper0(AccelStepper::HALF4WIRE , 8, 7, 5, 6);

 

3) Changing the physical pin order

As two pins are connected to each coil (see below picture) the pins may be flipped at the stepper or the Arduino connections. Just flip them coil wise like the pin order in the above AccelStepper object declaration.

Regards, Vinc

 

s-l500.jpg


Edited by Vinc_Vega

Regards, Vinc

real life: Royal Bavarian Airforce

online: VJS-GermanKnights.de

[sIGPIC][/sIGPIC]

Link to comment
Share on other sites

2 hours ago, Johan4668 said:

nullThis is more than 360... 410 degrees.. i solved it like this... then it has a 0 point.. but do you also need a end point?

image.png

image.png

image.png

Yes, you need a lower stop and an end stop. If the stepper has 630 steps for a 315 degree turn you may go 820 steps for your 410 degrees spiral. (630 * 410 / 315 = 820)

A reduction gear may also be used. Otherwise you need some zero detection like you planned for the second stepper of the altimeter.

Regards, Vinc

Regards, Vinc

real life: Royal Bavarian Airforce

online: VJS-GermanKnights.de

[sIGPIC][/sIGPIC]

Link to comment
Share on other sites

9 hours ago, Vinc_Vega said:

Yes, you need a lower stop and an end stop. If the stepper has 630 steps for a 315 degree turn you may go 820 steps for your 410 degrees spiral. (630 * 410 / 315 = 820)

A reduction gear may also be used. Otherwise you need some zero detection like you planned for the second stepper of the altimeter.

Regards, Vinc

Thanks... then iam going to experiment on that.. and to set 0 with a ir sensor.. what do I need to add?

 

And thanks for explaining and testing this is so helpful.. here i just started a discord for the 109 for people who likes to build it also.. and will also get the code on there so they don't have to go this journey I did... 

 

https://discord.gg/YGdhFuH2

If you like check it out.. and you can give advice.. 

Everything is going to be free and downloadeble and gauge by gauge..

I give you the result this weekend. 

Thanks again.. 

 

 

9 hours ago, No1sonuk said:

This is an option:
image.png

1:2.66 gearing (24:9 teeth) means a 180 degree servo can make a needle go 478 degrees.

I have this also.. the mw50 and feul for example

 

 

image-12.png

image-16.png

  • Like 1
Link to comment
Share on other sites

Hi Johan,

I've found the issue!

Don't know why, but I mixed up the adresses. After updating the plugins, the altimeter stepper worked fine with standard values. Sorry for that!

I updated all the old postings with the corrected adresses.

 

For the kilometer gauge you may use the following code, adress is 0x424a

  // Altimeter kilometer disk (0-13.000 m)
void onAltimeterCoarseptrChange(unsigned int newValue) {
  stepper0.runToNewPosition(map(newValue, 0, 56535, 0, 1260));
}
DcsBios::IntegerBuffer altimeterCoarseptrBuffer(0x424a, 0xffff, 0, onAltimeterCoarseptrChange);

Would you tell me the kind of IR sensor you intend to use?
Is there already an Arduino library or some code for that sensor available?

Regards, Vinc


Edited by Vinc_Vega

Regards, Vinc

real life: Royal Bavarian Airforce

online: VJS-GermanKnights.de

[sIGPIC][/sIGPIC]

Link to comment
Share on other sites

3 hours ago, Vinc_Vega said:

Hi Johan,

I've found the issue!

Don't know why, but I mixed up the adresses. After updating the plugins, the altimeter stepper worked fine with standard values. Sorry for that!

I updated all the old postings with the corrected adresses.

 

For the kilometer gauge you may use the following code, adress is 0x424a

  // Altimeter kilometer disk (0-13.000 m)
void onAltimeterCoarseptrChange(unsigned int newValue) {
  stepper0.runToNewPosition(map(newValue, 0, 56535, 0, 1260));
}
DcsBios::IntegerBuffer altimeterCoarseptrBuffer(0x424a, 0xffff, 0, onAltimeterCoarseptrChange);

Would you tell me the kind of IR sensor you intend to use?
Is there already an Arduino library or some code for that sensor available?

Regards, Vinc

 

Youmile 5-delige snelheidsmeetsensor IR-infrarood sleuven optische optocoupler-module Foto-onderbrekersensor voor motorsnelheidsdetectie of Arduino met encoders https://amzn.eu/d/bLbJ0FE

 

This one..

Link to comment
Share on other sites

On 3/18/2023 at 7:47 AM, Johan4668 said:

Thanks... then iam going to experiment on that.. and to set 0 with a ir sensor.. what do I need to add?

 

Hi Johan,

I merged Ian's code from that forum here (see page 1 for reference) for the 1000m pointer - including the zero detection - with that of the kilometer disk.

As I don't have an IR sensor yet, I simply used a push button at pin 11 to simulate the signal.

The 1000m pointer (AltimeterFineptr) is connected to pins 9, 10, 12 and 13, while the kilometer disk stepper (AltimeterCoarseptr) remains at pins 5 to 8.

So the rotary encoder still has pins 3 and 4 available and pins 0 to 2 are reserved for the RS485 option.

Maybe you have to tweak the values for maxSpeed and MaxAcceleration. You also may adjust the mapped values to the needs of your kilometer disk as 1260 steps are good for a 315 degree motion.

But at least you should have a sketch to start from.

Spoiler
#define DCSBIOS_IRQ_SERIAL

#include <AccelStepper.h>
#include "DcsBios.h"

struct StepperConfig {
 unsigned int maxSteps;
 unsigned int acceleration;
 unsigned int maxSpeed;
};


class Vid60Stepper : public DcsBios::Int16Buffer {
 private:
   AccelStepper& stepper;
   StepperConfig& stepperConfig;
   inline bool zeroDetected() { return digitalRead(irDetectorPin) == 1; }
   unsigned int (*map_function)(unsigned int);
   unsigned char initState;
   long currentStepperPosition;
   long lastAccelStepperPosition;
   unsigned char irDetectorPin;
   long zeroOffset;
   bool movingForward;
   bool lastZeroDetectState;

   long normalizeStepperPosition(long pos) {
     if (pos < 0) return pos + stepperConfig.maxSteps;
     if (pos >= stepperConfig.maxSteps) return pos - stepperConfig.maxSteps;
     return pos;
   }

   void updateCurrentStepperPosition() {
     // adjust currentStepperPosition to include the distance our stepper motor
     // was moved since we last updated it
     long movementSinceLastUpdate = stepper.currentPosition() - lastAccelStepperPosition;
     currentStepperPosition = normalizeStepperPosition(currentStepperPosition + movementSinceLastUpdate);
     lastAccelStepperPosition = stepper.currentPosition();
   }
 public:
   Vid60Stepper(unsigned int address, 
   AccelStepper& stepper, 
   StepperConfig& stepperConfig, 
   unsigned char irDetectorPin, 
   long zeroOffset, unsigned int (*map_function)(unsigned int)): Int16Buffer(address), 
   stepper(stepper), 
   stepperConfig(stepperConfig), 
   irDetectorPin(irDetectorPin), 
   zeroOffset(zeroOffset), 
   map_function(map_function), 
   initState(0), 
   currentStepperPosition(0), 
   lastAccelStepperPosition(0) 
   {
   }

   virtual void loop() {
     if (initState == 0) { // not initialized yet
       pinMode(irDetectorPin, INPUT);
       stepper.setMaxSpeed(stepperConfig.maxSpeed);
       stepper.setSpeed(1000);
       
       initState = 1;
     }
     if (initState == 1) {
       // move off zero if already there so we always get movement on reset
       // (to verify that the stepper is working)
       if (zeroDetected()) {
         stepper.runSpeed();
       } else {
           initState = 2;
       }
     }
     if (initState == 2) { // zeroing
       if (!zeroDetected()) {
         stepper.runSpeed();
       } else {
           stepper.setAcceleration(stepperConfig.acceleration);
           stepper.runToNewPosition(stepper.currentPosition() + zeroOffset);
           // tell the AccelStepper library that we are at position zero
           stepper.setCurrentPosition(0);
           lastAccelStepperPosition = 0;
           // set stepper acceleration in steps per second per second
           // (default is zero)
           stepper.setAcceleration(stepperConfig.acceleration);
           
           lastZeroDetectState = true;
           initState = 3;
       }
     }
     if (initState == 3) { // running normally
       
       // recalibrate when passing through zero position
       bool currentZeroDetectState = zeroDetected();
       if (!lastZeroDetectState && currentZeroDetectState && movingForward) {
         // we have moved from left to right into the 'zero detect window'
         // and are now at position 0
         lastAccelStepperPosition = stepper.currentPosition();
         currentStepperPosition = normalizeStepperPosition(zeroOffset);
       } else if (lastZeroDetectState && !currentZeroDetectState && !movingForward) {
         // we have moved from right to left out of the 'zero detect window'
         // and are now at position (maxSteps-1)
         lastAccelStepperPosition = stepper.currentPosition();
         currentStepperPosition = normalizeStepperPosition(stepperConfig.maxSteps + zeroOffset);
       }
       lastZeroDetectState = currentZeroDetectState;
       
       
       if (hasUpdatedData()) {
           // convert data from DCS to a target position expressed as a number of steps
           long targetPosition = (long)map_function(getData());

           updateCurrentStepperPosition();
           
           long delta = targetPosition - currentStepperPosition;
           
           // if we would move more than 180 degree counterclockwise, move clockwise instead
           if (delta < -((long)(stepperConfig.maxSteps/2))) delta += stepperConfig.maxSteps;
           // if we would move more than 180 degree clockwise, move counterclockwise instead
           if (delta > (stepperConfig.maxSteps/2)) delta -= (long)stepperConfig.maxSteps;

           movingForward = (delta >= 0);
           
           // tell AccelStepper to move relative to the current position
           stepper.move(delta);
           
       }
       stepper.run();
     }
   }
};

/* modify below this line */

/* define stepper parameters
  multiple Vid60Stepper instances can share the same StepperConfig object */
struct StepperConfig stepperConfig = 
 {
 1440,  // maxSteps
 8000, // maxSpeed
 16000 // acceleration
 };


// define AccelStepper instance
AccelStepper stepper1(AccelStepper::HALF4WIRE , 13, 12, 9, 10);
// define Vid60Stepper class that uses the AccelStepper instance defined in the line above
//           v-- arbitrary name
Vid60Stepper AltimeterFineptr(0x4248,          // address of stepper data
                            stepper1,         // name of AccelStepper instance
                            stepperConfig,   // StepperConfig struct instance
                            11,              // IR Detector Pin (must be HIGH in zero position)
                            0,               // zero offset
                            [](unsigned int newValue) -> unsigned int {
 /* this function needs to map newValue to the correct number of steps */
 return map(newValue, 0, 65535, 0, stepperConfig.maxSteps-1);
});

AccelStepper stepper0(AccelStepper::HALF4WIRE , 8, 7, 5, 6);

  // Altimeter kilometer disk (0-13.000 m)
void onAltimeterCoarseptrChange(unsigned int newValue) {
  stepper0.runToNewPosition(map(newValue, 0, 56535, 0, (1260-1)));
}
DcsBios::IntegerBuffer altimeterCoarseptrBuffer(0x424a, 0xffff, 0, onAltimeterCoarseptrChange);

// sea level knob
DcsBios::RotaryEncoder altPressSet("ALT_PRESS_SET", "-6400", "+6400", 3, 4);

void setup() {
 DcsBios::setup();
 pinMode(13, OUTPUT);
 zero_stepper0();
}

void loop() {
 PORTB |= (1<<5);
 PORTB &= ~(1<<5);
 DcsBios::loop();
}

void zero_stepper0(){
    stepper0.setMaxSpeed(16000);    //  maximum speed in steps per second. Must be > 0.
    stepper0.setAcceleration(8000);  //  desired acceleration in steps per second per second. Must be > 0.0
    stepper0.runToNewPosition(1260); // go to the upper end stop
    delay(250);
    stepper0.setCurrentPosition(1260); // set max steps
    stepper0.runToNewPosition(0);    // go to the lower end stop
    delay(250);
    stepper0.setCurrentPosition(0);  // set steps to zero
}

 

Regards, Vinc


Edited by Vinc_Vega

Regards, Vinc

real life: Royal Bavarian Airforce

online: VJS-GermanKnights.de

[sIGPIC][/sIGPIC]

Link to comment
Share on other sites

4 hours ago, Vinc_Vega said:

Hi Johan,

I merged Ian's code from that forum here (see page 1 for reference) for the 1000m pointer - including the zero detection - with that of the kilometer disk.

As I don't have an IR sensor yet, I simply used a push button at pin 11 to simulate the signal.

The 1000m pointer (AltimeterFineptr) is connected to pins 9, 10, 12 and 13, while the kilometer disk stepper (AltimeterCoarseptr) remains at pins 5 to 8.

So the rotary encoder still has pins 3 and 4 available and pins 0 to 2 are reserved for the RS485 option.

Maybe you have to tweak the values for maxSpeed and MaxAcceleration. You also may adjust the mapped values to the needs of your kilometer disk as 1260 steps are good for a 315 degree motion.

But at least you should have a sketch to start from.

  Hide contents
#define DCSBIOS_IRQ_SERIAL

#include <AccelStepper.h>
#include "DcsBios.h"

struct StepperConfig {
 unsigned int maxSteps;
 unsigned int acceleration;
 unsigned int maxSpeed;
};


class Vid60Stepper : public DcsBios::Int16Buffer {
 private:
   AccelStepper& stepper;
   StepperConfig& stepperConfig;
   inline bool zeroDetected() { return digitalRead(irDetectorPin) == 1; }
   unsigned int (*map_function)(unsigned int);
   unsigned char initState;
   long currentStepperPosition;
   long lastAccelStepperPosition;
   unsigned char irDetectorPin;
   long zeroOffset;
   bool movingForward;
   bool lastZeroDetectState;

   long normalizeStepperPosition(long pos) {
     if (pos < 0) return pos + stepperConfig.maxSteps;
     if (pos >= stepperConfig.maxSteps) return pos - stepperConfig.maxSteps;
     return pos;
   }

   void updateCurrentStepperPosition() {
     // adjust currentStepperPosition to include the distance our stepper motor
     // was moved since we last updated it
     long movementSinceLastUpdate = stepper.currentPosition() - lastAccelStepperPosition;
     currentStepperPosition = normalizeStepperPosition(currentStepperPosition + movementSinceLastUpdate);
     lastAccelStepperPosition = stepper.currentPosition();
   }
 public:
   Vid60Stepper(unsigned int address, 
   AccelStepper& stepper, 
   StepperConfig& stepperConfig, 
   unsigned char irDetectorPin, 
   long zeroOffset, unsigned int (*map_function)(unsigned int)): Int16Buffer(address), 
   stepper(stepper), 
   stepperConfig(stepperConfig), 
   irDetectorPin(irDetectorPin), 
   zeroOffset(zeroOffset), 
   map_function(map_function), 
   initState(0), 
   currentStepperPosition(0), 
   lastAccelStepperPosition(0) 
   {
   }

   virtual void loop() {
     if (initState == 0) { // not initialized yet
       pinMode(irDetectorPin, INPUT);
       stepper.setMaxSpeed(stepperConfig.maxSpeed);
       stepper.setSpeed(1000);
       
       initState = 1;
     }
     if (initState == 1) {
       // move off zero if already there so we always get movement on reset
       // (to verify that the stepper is working)
       if (zeroDetected()) {
         stepper.runSpeed();
       } else {
           initState = 2;
       }
     }
     if (initState == 2) { // zeroing
       if (!zeroDetected()) {
         stepper.runSpeed();
       } else {
           stepper.setAcceleration(stepperConfig.acceleration);
           stepper.runToNewPosition(stepper.currentPosition() + zeroOffset);
           // tell the AccelStepper library that we are at position zero
           stepper.setCurrentPosition(0);
           lastAccelStepperPosition = 0;
           // set stepper acceleration in steps per second per second
           // (default is zero)
           stepper.setAcceleration(stepperConfig.acceleration);
           
           lastZeroDetectState = true;
           initState = 3;
       }
     }
     if (initState == 3) { // running normally
       
       // recalibrate when passing through zero position
       bool currentZeroDetectState = zeroDetected();
       if (!lastZeroDetectState && currentZeroDetectState && movingForward) {
         // we have moved from left to right into the 'zero detect window'
         // and are now at position 0
         lastAccelStepperPosition = stepper.currentPosition();
         currentStepperPosition = normalizeStepperPosition(zeroOffset);
       } else if (lastZeroDetectState && !currentZeroDetectState && !movingForward) {
         // we have moved from right to left out of the 'zero detect window'
         // and are now at position (maxSteps-1)
         lastAccelStepperPosition = stepper.currentPosition();
         currentStepperPosition = normalizeStepperPosition(stepperConfig.maxSteps + zeroOffset);
       }
       lastZeroDetectState = currentZeroDetectState;
       
       
       if (hasUpdatedData()) {
           // convert data from DCS to a target position expressed as a number of steps
           long targetPosition = (long)map_function(getData());

           updateCurrentStepperPosition();
           
           long delta = targetPosition - currentStepperPosition;
           
           // if we would move more than 180 degree counterclockwise, move clockwise instead
           if (delta < -((long)(stepperConfig.maxSteps/2))) delta += stepperConfig.maxSteps;
           // if we would move more than 180 degree clockwise, move counterclockwise instead
           if (delta > (stepperConfig.maxSteps/2)) delta -= (long)stepperConfig.maxSteps;

           movingForward = (delta >= 0);
           
           // tell AccelStepper to move relative to the current position
           stepper.move(delta);
           
       }
       stepper.run();
     }
   }
};

/* modify below this line */

/* define stepper parameters
  multiple Vid60Stepper instances can share the same StepperConfig object */
struct StepperConfig stepperConfig = 
 {
 1440,  // maxSteps
 8000, // maxSpeed
 16000 // acceleration
 };


// define AccelStepper instance
AccelStepper stepper1(AccelStepper::HALF4WIRE , 13, 12, 9, 10);
// define Vid60Stepper class that uses the AccelStepper instance defined in the line above
//           v-- arbitrary name
Vid60Stepper AltimeterFineptr(0x4248,          // address of stepper data
                            stepper1,         // name of AccelStepper instance
                            stepperConfig,   // StepperConfig struct instance
                            11,              // IR Detector Pin (must be HIGH in zero position)
                            0,               // zero offset
                            [](unsigned int newValue) -> unsigned int {
 /* this function needs to map newValue to the correct number of steps */
 return map(newValue, 0, 65535, 0, stepperConfig.maxSteps-1);
});

AccelStepper stepper0(AccelStepper::HALF4WIRE , 8, 7, 5, 6);

  // Altimeter kilometer disk (0-13.000 m)
void onAltimeterCoarseptrChange(unsigned int newValue) {
  stepper0.runToNewPosition(map(newValue, 0, 56535, 0, (1260-1)));
}
DcsBios::IntegerBuffer altimeterCoarseptrBuffer(0x424a, 0xffff, 0, onAltimeterCoarseptrChange);

// sea level knob
DcsBios::RotaryEncoder altPressSet("ALT_PRESS_SET", "-6400", "+6400", 3, 4);

void setup() {
 DcsBios::setup();
 pinMode(13, OUTPUT);
 zero_stepper0();
}

void loop() {
 PORTB |= (1<<5);
 PORTB &= ~(1<<5);
 DcsBios::loop();
}

void zero_stepper0(){
    stepper0.setMaxSpeed(16000);    //  maximum speed in steps per second. Must be > 0.
    stepper0.setAcceleration(8000);  //  desired acceleration in steps per second per second. Must be > 0.0
    stepper0.runToNewPosition(1260); // go to the upper end stop
    delay(250);
    stepper0.setCurrentPosition(1260); // set max steps
    stepper0.runToNewPosition(0);    // go to the lower end stop
    delay(250);
    stepper0.setCurrentPosition(0);  // set steps to zero
}

 

Regards, Vinc

 

Your the best 🙂

this is also done..

Link to comment
Share on other sites

17 hours ago, Vinc_Vega said:

Did you manage to bring the speedometer to 410 degrees and back?

Regards, Vinc

i did not connect it yet but with hand it goes perfect...

the new nano is in.. so iam going to connect the alt gauge first

🙂 

Link to comment
Share on other sites

On 3/11/2023 at 11:18 PM, Vinc_Vega said:

No, unfortunately only Megas will work as masters. But each Mega can support up to 3 RS485 buses.

Edit: As a slave, the Mega, Uno and Nano boards do work.

Regards, Vinc

 

On the 3 buses for each mega, I have tried it and it works fine, it helped me simplify my wiring a lot

Cheers

 

Les

Link to comment
Share on other sites

On 3/19/2023 at 4:39 PM, Vinc_Vega said:

Did you manage to bring the speedometer to 410 degrees and back?

Regards, Vinc

 

It stops that is good.. I see the meter needle not moving and the km is and fast.. 

And on encoder the km disk moves..

 

Do we mis something here?

 


Edited by Johan4668
Link to comment
Share on other sites

Hi Johan,

the lower movie shows the starting sequence. The 1000m needle moves slow and stops at zero. The km disk goes to the upper stop and back to zero. It's intended to do so. If you want to slow down the km disk at startup you have to lower the MaxSpeed within the Zero_Stepper0 routine at the end of the sketch let's say to 1000 and acceleration to 2000.

Furthermore, I think that the direction of the 1000m needle has to be inverted. Change the pins to 9, 10, 13, 12 within the AccelStepper declaration.

But what is shown in the upper movie? The km disk should not move when turning the encoder (or at least only from 0 to 1.

Regards, Vinc


Edited by Vinc_Vega

Regards, Vinc

real life: Royal Bavarian Airforce

online: VJS-GermanKnights.de

[sIGPIC][/sIGPIC]

Link to comment
Share on other sites

4 minutes ago, Vinc_Vega said:

Hi Johan,

the lower movie shows the starting sequence. The 1000m needle moves slow and stops at zero. The km disk goes to the upper stop and back to zero. It's intended to do so. If you want to slow down the km disk at startup you have to lower the MaxSpeed within the Zero_Stepper0 routine at the end of the sketch let's say to 1000 and acceleration to 2000.

But what is shown in the upper movie? The km disk should not move when turning the encoder (or at least only from 0 to 1.

Regards, Vinc

the lower is ok.. the startup..

the upper is in DCS flight.. the 0 - 1000 meter needle is not moving and the km disk is moving fast.. on climbing 500 meters

Link to comment
Share on other sites

On 3/19/2023 at 3:30 PM, Johan4668 said:
#define DCSBIOS_IRQ_SERIAL

#include <AccelStepper.h>
#include "DcsBios.h"

struct StepperConfig {
 unsigned int maxSteps;
 unsigned int acceleration;
 unsigned int maxSpeed;
};


class Vid60Stepper : public DcsBios::Int16Buffer {
 private:
   AccelStepper& stepper;
   StepperConfig& stepperConfig;
   inline bool zeroDetected() { return digitalRead(irDetectorPin) == 1; }
   unsigned int (*map_function)(unsigned int);
   unsigned char initState;
   long currentStepperPosition;
   long lastAccelStepperPosition;
   unsigned char irDetectorPin;
   long zeroOffset;
   bool movingForward;
   bool lastZeroDetectState;

   long normalizeStepperPosition(long pos) {
     if (pos < 0) return pos + stepperConfig.maxSteps;
     if (pos >= stepperConfig.maxSteps) return pos - stepperConfig.maxSteps;
     return pos;
   }

   void updateCurrentStepperPosition() {
     // adjust currentStepperPosition to include the distance our stepper motor
     // was moved since we last updated it
     long movementSinceLastUpdate = stepper.currentPosition() - lastAccelStepperPosition;
     currentStepperPosition = normalizeStepperPosition(currentStepperPosition + movementSinceLastUpdate);
     lastAccelStepperPosition = stepper.currentPosition();
   }
 public:
   Vid60Stepper(unsigned int address, 
   AccelStepper& stepper, 
   StepperConfig& stepperConfig, 
   unsigned char irDetectorPin, 
   long zeroOffset, unsigned int (*map_function)(unsigned int)): Int16Buffer(address), 
   stepper(stepper), 
   stepperConfig(stepperConfig), 
   irDetectorPin(irDetectorPin), 
   zeroOffset(zeroOffset), 
   map_function(map_function), 
   initState(0), 
   currentStepperPosition(0), 
   lastAccelStepperPosition(0) 
   {
   }

   virtual void loop() {
     if (initState == 0) { // not initialized yet
       pinMode(irDetectorPin, INPUT);
       stepper.setMaxSpeed(stepperConfig.maxSpeed);
       stepper.setSpeed(1000);
       
       initState = 1;
     }
     if (initState == 1) {
       // move off zero if already there so we always get movement on reset
       // (to verify that the stepper is working)
       if (zeroDetected()) {
         stepper.runSpeed();
       } else {
           initState = 2;
       }
     }
     if (initState == 2) { // zeroing
       if (!zeroDetected()) {
         stepper.runSpeed();
       } else {
           stepper.setAcceleration(stepperConfig.acceleration);
           stepper.runToNewPosition(stepper.currentPosition() + zeroOffset);
           // tell the AccelStepper library that we are at position zero
           stepper.setCurrentPosition(0);
           lastAccelStepperPosition = 0;
           // set stepper acceleration in steps per second per second
           // (default is zero)
           stepper.setAcceleration(stepperConfig.acceleration);
           
           lastZeroDetectState = true;
           initState = 3;
       }
     }
     if (initState == 3) { // running normally
       
       // recalibrate when passing through zero position
       bool currentZeroDetectState = zeroDetected();
       if (!lastZeroDetectState && currentZeroDetectState && movingForward) {
         // we have moved from left to right into the 'zero detect window'
         // and are now at position 0
         lastAccelStepperPosition = stepper.currentPosition();
         currentStepperPosition = normalizeStepperPosition(zeroOffset);
       } else if (lastZeroDetectState && !currentZeroDetectState && !movingForward) {
         // we have moved from right to left out of the 'zero detect window'
         // and are now at position (maxSteps-1)
         lastAccelStepperPosition = stepper.currentPosition();
         currentStepperPosition = normalizeStepperPosition(stepperConfig.maxSteps + zeroOffset);
       }
       lastZeroDetectState = currentZeroDetectState;
       
       
       if (hasUpdatedData()) {
           // convert data from DCS to a target position expressed as a number of steps
           long targetPosition = (long)map_function(getData());

           updateCurrentStepperPosition();
           
           long delta = targetPosition - currentStepperPosition;
           
           // if we would move more than 180 degree counterclockwise, move clockwise instead
           if (delta < -((long)(stepperConfig.maxSteps/2))) delta += stepperConfig.maxSteps;
           // if we would move more than 180 degree clockwise, move counterclockwise instead
           if (delta > (stepperConfig.maxSteps/2)) delta -= (long)stepperConfig.maxSteps;

           movingForward = (delta >= 0);
           
           // tell AccelStepper to move relative to the current position
           stepper.move(delta);
           
       }
       stepper.run();
     }
   }
};

/* modify below this line */

/* define stepper parameters
  multiple Vid60Stepper instances can share the same StepperConfig object */
struct StepperConfig stepperConfig = 
 {
 1440,  // maxSteps
 8000, // maxSpeed
 16000 // acceleration
 };


// define AccelStepper instance
AccelStepper stepper1(AccelStepper::HALF4WIRE , 13, 12, 9, 10);
// define Vid60Stepper class that uses the AccelStepper instance defined in the line above
//           v-- arbitrary name
Vid60Stepper AltimeterFineptr(0x4248,          // address of stepper data
                            stepper1,         // name of AccelStepper instance
                            stepperConfig,   // StepperConfig struct instance
                            11,              // IR Detector Pin (must be HIGH in zero position)
                            0,               // zero offset
                            [](unsigned int newValue) -> unsigned int {
 /* this function needs to map newValue to the correct number of steps */
 return map(newValue, 0, 65535, 0, stepperConfig.maxSteps-1);
});

AccelStepper stepper0(AccelStepper::HALF4WIRE , 8, 7, 5, 6);

  // Altimeter kilometer disk (0-13.000 m)
void onAltimeterCoarseptrChange(unsigned int newValue) {
  stepper0.runToNewPosition(map(newValue, 0, 56535, 0, (1260-1)));
}
DcsBios::IntegerBuffer altimeterCoarseptrBuffer(0x424a, 0xffff, 0, onAltimeterCoarseptrChange);

// sea level knob
DcsBios::RotaryEncoder altPressSet("ALT_PRESS_SET", "-6400", "+6400", 3, 4);

void setup() {
 DcsBios::setup();
 pinMode(13, OUTPUT);
 zero_stepper0();
}

void loop() {
 PORTB |= (1<<5);
 PORTB &= ~(1<<5);
 DcsBios::loop();
}

void zero_stepper0(){
    stepper0.setMaxSpeed(16000);    //  maximum speed in steps per second. Must be > 0.
    stepper0.setAcceleration(8000);  //  desired acceleration in steps per second per second. Must be > 0.0
    stepper0.runToNewPosition(1260); // go to the upper end stop
    delay(250);
    stepper0.setCurrentPosition(1260); // set max steps
    stepper0.runToNewPosition(0);    // go to the lower end stop
    delay(250);
    stepper0.setCurrentPosition(0);  // set steps to zero
}

 

It's the code you send me..

Link to comment
Share on other sites

Can somebody please confirm the addresses for the altimeter of the BF-109?

I have read out the Bf-109K-4.json file from the "AppData\Roaming\DCS-BIOS\control-reference-json" folder. But as I don't use the Flightpanels fork, the file may be outdated.

Altimeter_FinePtr (1000m needle) 0x4248 (decimal 16.968)

Altimeter_CoarsePtr (km disk) 0x424a (decimal 16.970)

Altimeter_Pressure (pressure disk ) 0x424c (decimal 16.972)

 

 

Johan,

What happen to your gauge if you change the address of the 1000m needle and the km disk according to values read out of the Flightpanel's Bf-109K-4.jsonp file?

try to change the hexadecimal addresses in line 165

DcsBios::IntegerBuffer altimeterCoarseptrBuffer(0x424a, 0xffff, 0, onAltimeterCoarseptrChange);

into

DcsBios::IntegerBuffer altimeterCoarseptrBuffer(0x424c, 0xffff, 0, onAltimeterCoarseptrChange);

  and that of line 149

Vid60Stepper AltimeterFineptr(0x4248,          // address of stepper data

into

Vid60Stepper AltimeterFineptr(0x424a,          // address of stepper data

 

Regards, Vinc


Edited by Vinc_Vega

Regards, Vinc

real life: Royal Bavarian Airforce

online: VJS-GermanKnights.de

[sIGPIC][/sIGPIC]

Link to comment
Share on other sites

31 minutes ago, Vinc_Vega said:

Can somebody please confirm the addresses for the altimeter of the BF-109?

I have read out the Bf-109K-4.json file from the "AppData\Roaming\DCS-BIOS\control-reference-json" folder. But as I don't use the Flightpanels fork, the file may be outdated.

Altimeter_FinePtr (1000m needle) 0x4248 (decimal 16.968)

Altimeter_CoarsePtr (km disk) 0x424a (decimal 16.970)

Altimeter_Pressure (pressure disk ) 0x424c (decimal 16.972)

 

From the latest I have:

Altimeter_CoarsePtrBf-109K-4/ALTIMETER_COARSEPTR
 
DcsBios::ServoOutput altimeterCoarseptr(0x424c, PIN, 544, 2400);
Altimeter_FinePtrBf-109K-4/ALTIMETER_FINEPTR
 
DcsBios::ServoOutput altimeterFineptr(0x424a, PIN, 544, 2400);
Altimeter_PressureBf-109K-4/ALTIMETER_PRESSURE
 
DcsBios::ServoOutput altimeterPressure(0x424e, PIN, 544, 2400);
  • Thanks 1
Link to comment
Share on other sites

Thank you No1sonuk, so the issue can be explained.

Johan, please change the hexadecimal values for both steppers like proposed above.

 

adjusted code below

Spoiler
#define DCSBIOS_IRQ_SERIAL

#include <AccelStepper.h>
#include "DcsBios.h"

struct StepperConfig {
 unsigned int maxSteps;
 unsigned int acceleration;
 unsigned int maxSpeed;
};


class Vid60Stepper : public DcsBios::Int16Buffer {
 private:
   AccelStepper& stepper;
   StepperConfig& stepperConfig;
   inline bool zeroDetected() { return digitalRead(irDetectorPin) == 1; }
   unsigned int (*map_function)(unsigned int);
   unsigned char initState;
   long currentStepperPosition;
   long lastAccelStepperPosition;
   unsigned char irDetectorPin;
   long zeroOffset;
   bool movingForward;
   bool lastZeroDetectState;

   long normalizeStepperPosition(long pos) {
     if (pos < 0) return pos + stepperConfig.maxSteps;
     if (pos >= stepperConfig.maxSteps) return pos - stepperConfig.maxSteps;
     return pos;
   }

   void updateCurrentStepperPosition() {
     // adjust currentStepperPosition to include the distance our stepper motor
     // was moved since we last updated it
     long movementSinceLastUpdate = stepper.currentPosition() - lastAccelStepperPosition;
     currentStepperPosition = normalizeStepperPosition(currentStepperPosition + movementSinceLastUpdate);
     lastAccelStepperPosition = stepper.currentPosition();
   }
 public:
   Vid60Stepper(unsigned int address, 
   AccelStepper& stepper, 
   StepperConfig& stepperConfig, 
   unsigned char irDetectorPin, 
   long zeroOffset, unsigned int (*map_function)(unsigned int)): Int16Buffer(address), 
   stepper(stepper), 
   stepperConfig(stepperConfig), 
   irDetectorPin(irDetectorPin), 
   zeroOffset(zeroOffset), 
   map_function(map_function), 
   initState(0), 
   currentStepperPosition(0), 
   lastAccelStepperPosition(0) 
   {
   }

   virtual void loop() {
     if (initState == 0) { // not initialized yet
       pinMode(irDetectorPin, INPUT);
       stepper.setMaxSpeed(stepperConfig.maxSpeed);
       stepper.setSpeed(1000);
       
       initState = 1;
     }
     if (initState == 1) {
       // move off zero if already there so we always get movement on reset
       // (to verify that the stepper is working)
       if (zeroDetected()) {
         stepper.runSpeed();
       } else {
           initState = 2;
       }
     }
     if (initState == 2) { // zeroing
       if (!zeroDetected()) {
         stepper.runSpeed();
       } else {
           stepper.setAcceleration(stepperConfig.acceleration);
           stepper.runToNewPosition(stepper.currentPosition() + zeroOffset);
           // tell the AccelStepper library that we are at position zero
           stepper.setCurrentPosition(0);
           lastAccelStepperPosition = 0;
           // set stepper acceleration in steps per second per second
           // (default is zero)
           stepper.setAcceleration(stepperConfig.acceleration);
           
           lastZeroDetectState = true;
           initState = 3;
       }
     }
     if (initState == 3) { // running normally
       
       // recalibrate when passing through zero position
       bool currentZeroDetectState = zeroDetected();
       if (!lastZeroDetectState && currentZeroDetectState && movingForward) {
         // we have moved from left to right into the 'zero detect window'
         // and are now at position 0
         lastAccelStepperPosition = stepper.currentPosition();
         currentStepperPosition = normalizeStepperPosition(zeroOffset);
       } else if (lastZeroDetectState && !currentZeroDetectState && !movingForward) {
         // we have moved from right to left out of the 'zero detect window'
         // and are now at position (maxSteps-1)
         lastAccelStepperPosition = stepper.currentPosition();
         currentStepperPosition = normalizeStepperPosition(stepperConfig.maxSteps + zeroOffset);
       }
       lastZeroDetectState = currentZeroDetectState;
       
       
       if (hasUpdatedData()) {
           // convert data from DCS to a target position expressed as a number of steps
           long targetPosition = (long)map_function(getData());

           updateCurrentStepperPosition();
           
           long delta = targetPosition - currentStepperPosition;
           
           // if we would move more than 180 degree counterclockwise, move clockwise instead
           if (delta < -((long)(stepperConfig.maxSteps/2))) delta += stepperConfig.maxSteps;
           // if we would move more than 180 degree clockwise, move counterclockwise instead
           if (delta > (stepperConfig.maxSteps/2)) delta -= (long)stepperConfig.maxSteps;

           movingForward = (delta >= 0);
           
           // tell AccelStepper to move relative to the current position
           stepper.move(delta);
           
       }
       stepper.run();
     }
   }
};

/* modify below this line */

/* define stepper parameters
  multiple Vid60Stepper instances can share the same StepperConfig object */
struct StepperConfig stepperConfig = 
 {
 1440,  // maxSteps
 4000, // maxSpeed
 8000 // acceleration
 };


// define AccelStepper instance
AccelStepper stepper1(AccelStepper::HALF4WIRE , 10, 11, 13, 12);
// define Vid60Stepper class that uses the AccelStepper instance defined in the line above
//           v-- arbitrary name
Vid60Stepper AltimeterFineptr(0x424a,          // address of stepper data
                            stepper1,         // name of AccelStepper instance
                            stepperConfig,   // StepperConfig struct instance
                            9,              // IR Detector Pin (must be HIGH in zero position)
                            0,               // zero offset
                            [](unsigned int newValue) -> unsigned int {
 /* this function needs to map newValue to the correct number of steps */
 return map(newValue, 0, 65535, 0, stepperConfig.maxSteps-1);
});

AccelStepper stepper0(AccelStepper::HALF4WIRE , 8, 7, 5, 6);

  // Altimeter kilometer disk (0-13.000 m)
void onAltimeterCoarseptrChange(unsigned int newValue) {
  stepper0.runToNewPosition(map(newValue, 0, 56535, 0, (1260-1)));
}
DcsBios::IntegerBuffer altimeterCoarseptrBuffer(0x424c, 0xffff, 0, onAltimeterCoarseptrChange);

// sea level knob
DcsBios::RotaryEncoder altPressSet("ALT_PRESS_SET", "-3200", "+3200", 3, 4);

void setup() {
 DcsBios::setup();
 pinMode(13, OUTPUT);
 zero_stepper0();
}

void loop() {
 PORTB |= (1<<5);
 PORTB &= ~(1<<5);
 DcsBios::loop();
}

void zero_stepper0(){
    stepper0.setMaxSpeed(8000);    //  maximum speed in steps per second. Must be > 0.
    stepper0.setAcceleration(4000);  //  desired acceleration in steps per second per second. Must be > 0.0
    stepper0.runToNewPosition(1260); // go to the upper end stop
    delay(250);
    stepper0.setCurrentPosition(1260); // set max steps
    stepper0.runToNewPosition(0);    // go to the lower end stop
    delay(250);
    stepper0.setCurrentPosition(0);  // set steps to zero
}

 

Regards, Vinc


Edited by Vinc_Vega
  • Like 1

Regards, Vinc

real life: Royal Bavarian Airforce

online: VJS-GermanKnights.de

[sIGPIC][/sIGPIC]

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...