lesthegrngo Posted March 12, 2020 Posted March 12, 2020 (edited) Hi guys, I'm still moving this all forward slowly, now that I have a substantial amount of the cockpit if not finished, then working in need of tidy up. one of the items on the list was the altimeter, which is one of the very few (physical) gauges I am making that requires unlimited rotation. Middlefart has kindly provided us all with his rather nice scrolling OLED display sketch, so now all that remains on that particular gauge is to be able to set the zero position using either an IR optocoupler or a hall effect sensor. My preference for the IR optocoupler route is simply because I have one supplied as part of an arduino starter set. I found this sketch on this forum thread https://forums.eagle.ru/showthread.php?t=145193 // include AccelStepper library #include <AccelStepper.h> // include DcsBios library #include <DcsBios.h> #include <Servo.h> // DcsBios-related declarations DcsBios:ProtocolParser parser; #define STEPS_PER_REVOLUTION 240 #define ZERO_OFFSET 0 AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5 int currentStepperPosition = 0; // current stepper position (in steps, from 0 to STEPS_PER_REVOLUTION-1) signed long lastAccelStepperPosition; void setup() { Serial.begin(250000); pinMode (12,INPUT); // LOW when in zero position, HIGH otherwise // set up stepper motor for zeroing stepper.setMaxSpeed(1000); stepper.setSpeed(500); // run clockwise until we detect the zero position while (digitalRead (12)==1) { stepper.runSpeed(); } // add zero offset stepper.runToNewPosition(stepper.currentPosition() + ZERO_OFFSET); // 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(1000); } void loop() { // handle DcsBios communication while (Serial.available()) { parser.processChar(Serial.read()); } DcsBios:PollingInput::pollInputs(); // move stepper motor stepper.run(); } void onDcsBiosWrite(unsigned int address, unsigned int value) { if (address == 0x107e) { digitalWrite (13,1); unsigned int alt100ftValue = (value & 0xffff) >> 0; // convert data from DCS to a target position expressed as a number of steps int targetPosition = map(alt100ftValue, 0, 65535, 0, STEPS_PER_REVOLUTION-1); // adjust currentStepperPosition to include the distance our stepper motor // was moved since we last updated it int movementSinceLastUpdate = stepper.currentPosition() - lastAccelStepperPosition; currentStepperPosition += movementSinceLastUpdate; lastAccelStepperPosition = stepper.currentPosition(); if (currentStepperPosition < 0) currentStepperPosition += STEPS_PER_REVOLUTION; if (currentStepperPosition > STEPS_PER_REVOLUTION) currentStepperPosition -= STEPS_PER_REVOLUTION; int delta = targetPosition - currentStepperPosition; // if we would move more than 180 degree counterclockwise, move clockwise instead if (delta < -(STEPS_PER_REVOLUTION/2)) delta += STEPS_PER_REVOLUTION; // if we would move more than 180 degree clockwise, move counterclockwise instead if (delta > (STEPS_PER_REVOLUTION/2)) delta -= STEPS_PER_REVOLUTION; // tell AccelStepper to move relative to the current position stepper.move(delta); I'm using an X27 type stepper motor, which has already been modified to remove the limiting pin inside. The sketch has to be changed for use with a stepper driver (an A4988 module) as this sketch seems to drive the stepper directly. The optocoupler module is one of these https://www.ebay.com/itm/TCRT5000-IR-Infrared-Line-Track-Follower-Sensor-Obstacle-Avoidance-Module/202058803237?hash=item2f0ba4a825:g:z-8AAOSwSZFZwAJD So I am going to put a test together, then see if I can successfully get the sketch working correctly with the hardware. If anyone has experience of this and can advise as ever I would be grateful for the input Wish me luck! Cheers Les Edited March 12, 2020 by lesthegrngo
draken152 Posted March 12, 2020 Posted March 12, 2020 For inspiration I made it like this [sIGPIC][/sIGPIC] Building FW190D pit ,,To Dora with love" http://forums.eagle.ru/showthread.php?t=132743
lesthegrngo Posted March 12, 2020 Author Posted March 12, 2020 Thanks, looks like some great info there Cheers Les
lesthegrngo Posted March 23, 2020 Author Posted March 23, 2020 The unfortunate situation with Coronavirus has had the collateral effect of giving me chance to work on some bits and pieces for my sim pit. I knocked together the sketch below, which with my optocoupler is working to zero the gauge. However once it has zeroed, the gauge never moves again! Is there anything obvious wrong with it? #define DCSBIOS_IRQ_SERIAL #include <AccelStepper.h> #include "DcsBios.h" struct StepperConfig { unsigned int maxSteps; unsigned int acceleration; unsigned int maxSpeed; }; class Vid29Stepper : 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: Vid29Stepper(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 = { 400, // maxSteps 2200, // maxSpeed 1000 // acceleration }; // define AccelStepper instance AccelStepper stepper(AccelStepper::DRIVER, 11, 10); // define Vid29Stepper class that uses the AccelStepper instance defined in the line above // v-- arbitrary name Vid29Stepper alt100ftPointer(0x107e, // address of stepper data stepper, // 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); }); void setup() { DcsBios::setup(); } void loop() { DcsBios::loop(); } Cheers Les
Recommended Posts