shreddersa Posted November 14, 2019 Share Posted November 14, 2019 For my Spitfire Cockpit I am using an actuator with bungees to increase the tension in the roll and yaw controls with increasing airspeed. I am trying to figure out whether I can simply read the DCS-BIOS value for the Airspeed from the AIRSPEEDGAUGE value? Sorry, I have controlled actuators with Arduino and a motor control shield before but am new to integrating this into DCS-BIOS. I have provided my proposed code below. Any input would be greatly appreciated! /* Tell DCS-BIOS to use a serial connection and use interrupt-driven communication. The main program will be interrupted to prioritize processing incoming data. This should work on any Arduino that has an ATMega328 controller (Uno, Pro Mini, many others). */ #define DCSBIOS_IRQ_SERIAL #include "DcsBios.h" /* paste code snippets from the reference documentation here */ DcsBios::Potentiometer trimWheel("TRIM_WHEEL", A1); DcsBios::Potentiometer rtrimWheel("RTRIM_WHEEL", A2); DcsBios::Switch2Pos fuelPump("FUEL_PUMP", 2); DcsBios::Switch2Pos diluter("DILUTER", 3); DcsBios::Switch2Pos diluterCover("DILUTER_COVER", 4); DcsBios::Switch2Pos radTest("RAD_TEST", 5); DcsBios::Switch2Pos radTestCover("RAD_TEST_COVER", 6); DcsBios::Switch2Pos msTest("MS_TEST", 7); DcsBios::Switch2Pos msTestCover("MS_TEST_COVER", 33); DcsBios::Switch2Pos hatch("HATCH", 34); DcsBios::Switch2Pos sideDoor("SIDE_DOOR", 35); DcsBios::Switch2Pos pitot("PITOT", 36); DcsBios::Switch2Pos radiator("RADIATOR", 37); DcsBios::Switch2Pos wobblePump("WOBBLE_PUMP", 38); DcsBios::RotaryEncoder uc("UC", "DEC", "INC", 14, 15); DcsBios::Switch3Pos morseDnMode("MORSE_DN_MODE", 16, 17); DcsBios::Switch2Pos morseKey("MORSE_KEY", 18); DcsBios::Switch3Pos morseUpMode("MORSE_UP_MODE", 19, 20); DcsBios::Switch2Pos iffB("IFF_B", 21); DcsBios::Switch2Pos iffD("IFF_D", 22); DcsBios::Switch2Pos iffCover("IFF_COVER", 23); DcsBios::Switch2Pos iff0("IFF_0", 24); DcsBios::Switch2Pos iff1("IFF_1", 25); DcsBios::Switch2Pos droptankCock("DROPTANK_COCK", 26); DcsBios::Switch2Pos droptankJett("DROPTANK_JETT", 27); DcsBios::Switch2Pos ucEmer("UC_EMER", 28); DcsBios::Switch2Pos deicer("DEICER", 29); DcsBios::Switch2Pos hatchJettison("HATCH_JETTISON", 30); //This is where I have added my own initiation routine steps: /* Arduino Airspeed Force Feedback Control Rev1 - test program code by: Roel Stausebach, incorporating the work by various before me The code addresses the following elements: MonsterMoto control Indicated airspeed from Airspeedgauge value of DCS-BIOS Actuator Potentiometer - to provide current position. This test script assumes the potentiometer value for the actuator to range between 0 and 1023. 1. OPERATION - READ THE "AIRSPEEDGAUGE" value, ADJUST THE ACTUATOR TO THAT POSITION The range can be between 0 and 65535. For the Spitfire the full gauge reading is 480mph We want full effect of the Force Feedback to be at 300mph already, so range value 41000 So actuator will move for 0 to 41000. Arduino has an analogRead range from 0 to 1023, we assign AirSpeedConvert value to this. and an analogWrite range only from 0 to 255, therefore the data from the actuator potentiometer needs to be converted to fit into the smaller range */ const int CS_THRESHOLD = 135; //this is the overload value for 5A int inApin = 39; // INA: Clockwise input int inBpin =40; // INB: Counter-clockwise input int pwmpin = 8; // PWM OUTput int AIRSPEED = 0; // Set AIRSPEED TO 0 int AirSpeedConvert = 0; //Set initial value int pwmSpeed = 255; // Set initial ACTUATOR speed to max. int cspin = 2; // these constants are set for picking up the actuator position: const int actuatorPin = A3; // the pin that the actuator potentiometer is attached to int actuatorPosInit = analogRead(actuatorPin); //this will only ever be a value between 0 and 400 int actuatorPosNow = actuatorPosInit; // void setup() { DcsBios::setup(); } void onAirspeedgaugeChange(unsigned int newValue) { /* your code here */ // and this is where I have added my own loop // read the Actuator potentiometer: actuatorPosNow = analogRead(actuatorPin); } //Determine what the current position SHOULD be based on airspeed: AirSpeedConvert = AIRSPEEDGAUGE //NOT SURE I CAN SIMPLY READ THIS FROM DCS-BIOS??? if (AirSpeedConvert > 41000) (AirSpeedConvert = 41000) AIRSPEED = AirSpeedConvert/41 //if AIRSPEED is same as actuator position, switch motor off if (AIRSPEED = actuatorPosNow) { motorOff(); } //if AIRSPEED is higher, start forward motion if (AIRSPEED > actuatorPosNow) { digitalWrite(inApin, HIGH); //Direction Forward analogWrite(pwmpin, pwmSpeed); } //if AIRSPEED is lower, start Reverse motion if(AIRSPEED < actuatorPosNow) { digitalWrite(inBpin, HIGH); //Direction Reverse analogWrite(pwmpin, pwmSpeed); } } DcsBios::IntegerBuffer airspeedgaugeBuffer(0x5436, 0xffff, 0, onAirspeedgaugeChange); void loop() { DcsBios::loop(); } void motorOff() { digitalWrite(inApin, LOW); digitalWrite(inBpin, LOW); analogWrite(pwmpin, 0); } Link to comment Share on other sites More sharing options...
youngque Posted November 15, 2019 Share Posted November 15, 2019 What kind of hardware are you using for your actuator system? Quentin Link to comment Share on other sites More sharing options...
shreddersa Posted November 15, 2019 Author Share Posted November 15, 2019 What kind of hardware are you using for your actuator system? Quentin Simple cheap brand actuator with potentiometer. Link to comment Share on other sites More sharing options...
FSFIan Posted November 16, 2019 Share Posted November 16, 2019 //Determine what the current position SHOULD be based on airspeed: AirSpeedConvert = AIRSPEEDGAUGE //NOT SURE I CAN SIMPLY READ THIS FROM DCS-BIOS??? The callback function receives the value as a function parameter (named newValue in the code snippets). Try the following: AirSpeedConvert = newValue; DCS-BIOS | How to export CMSP, RWR, etc. through MonitorSetup.lua Link to comment Share on other sites More sharing options...
shreddersa Posted November 16, 2019 Author Share Posted November 16, 2019 Ian;4109302']The callback function receives the value as a function parameter (named newValue in the code snippets). Try the following: AirSpeedConvert = newValue; Many thanks Ian, will give that a try! :thumbup: Link to comment Share on other sites More sharing options...
shreddersa Posted May 7, 2020 Author Share Posted May 7, 2020 Solution! Ian, many thanks for pointing me in the right direction. I have used advice from you, others on the forum and external tutorials and guidance. After much experimentation, headscratching, research and long hours I finally managed to come up with the right combination of elements in the code. The actuator now works beautifully, pulling the bungee cords tight to tension the action of the controls. It uses the airspeed reading to move the full range. My publishing it the sketch here is a small token of appreciation for all the help received. Hopefully it will help others too. This is the full sketch::music_whistling: /* Tell DCS-BIOS to use a serial connection and use interrupt-driven communication. The main program will be interrupted to prioritize processing incoming data. This should work on any Arduino that has an ATMega328 controller (Uno, Pro Mini, many others). */ #define DCSBIOS_IRQ_SERIAL #include "DcsBios.h" DcsBios::PotentiometerEWMA<5, 128, 5> trimWheel("TRIM_WHEEL", A1); DcsBios::PotentiometerEWMA<5, 128, 5> rtrimWheel("RTRIM_WHEEL", A2); DcsBios::Switch2Pos fuelPump("FUEL_PUMP", 2); DcsBios::Switch2Pos diluter("DILUTER", 3); DcsBios::Switch2Pos diluterCover("DILUTER_COVER", 4, true); DcsBios::Switch2Pos radTest("RAD_TEST", 5); DcsBios::Switch2Pos radTestCover("RAD_TEST_COVER", 6, true); DcsBios::Switch2Pos msTest("MS_TEST", 7); DcsBios::Switch2Pos msTestCover("MS_TEST_COVER", 33, true); DcsBios::Switch2Pos hatch("HATCH", 34); DcsBios::Switch2Pos sideDoor("SIDE_DOOR", 35); DcsBios::Switch2Pos pitot("PITOT", 36); DcsBios::Switch2Pos radiator("RADIATOR", 37); DcsBios::Switch2Pos wobblePump("WOBBLE_PUMP", 38); DcsBios::RotaryEncoder uc("UC", "DEC", "INC", 14, 15); DcsBios::Switch3Pos morseDnMode("MORSE_DN_MODE", 17, 16); DcsBios::Switch2Pos morseKey("MORSE_KEY", 18); DcsBios::RotaryEncoder morseUpMode("MORSE_UP_MODE", "DEC", "INC", 19, 20); DcsBios::Switch2Pos iffB("IFF_B", 21); DcsBios::Switch2Pos iffD("IFF_D", 22); DcsBios::Switch2Pos iffCover("IFF_COVER", 23); DcsBios::Switch2Pos iff0("IFF_0", 24); DcsBios::Switch2Pos iff1("IFF_1", 25); DcsBios::Switch2Pos droptankCock("DROPTANK_COCK", 26); DcsBios::Switch2Pos droptankJett("DROPTANK_JETT", 27); DcsBios::Switch2Pos ucEmer("UC_EMER", 28); DcsBios::Switch2Pos deicer("DEICER", 29); /* Arduino Airspeed Force Feedback Control Rev6 code by: Roel Stausebach, building on work by various before me The code addresses the following elements: MiniMonsterMoto control (VNH2SP30 Monster Motor Module, single channel) Indicated airspeed from Airspeedgauge value of DCS-BIOS Actuator Potentiometer - to provide current position. 1. OPERATION - READ THE "AIRSPEEDGAUGE" value, ADJUST THE ACTUATOR TO THAT POSITION The range can be between 0 and 65535. For the Spitfire the full gauge reading is 480mph We want full effect of the Force Feedback to be at 480mph Arduino has an analogRead range from 0 to 1023, and the actuator potentiometer is usually less than this. (see below, in our case it is 132 to 1020)We assign the AirSpeedConvert value to this. In the Prototype the potentiometer range runs from 132 retracted to 1020 extended. This was established using the Actuator_Range_Test sketch and is something that will need to be done for each different actuator. To calculate the values to be used: full range of movement: 1020-132=888 AirSpeedConvert runs from 0 to 65535=480mph So a speed range of 65535 is represented by 888 on the potentiometer range Thus a factor of 65535/888=73.8+132 to convert to AIRSPEED (the 132 is added as it is the miniumum reading on the actuator potentiometer) Lets say airspeed is 280mph then: AirSpeedConvert=280/480x65535=38228.75 and AIRSPEED=(38228.75/73.8)+132=650 and lets assume the current actuator position actuatorPosNow reads 381, so now we need to move the actuator to a position where the readout is 650 */ // Variables that remain the same: const int CS_THRESHOLD = 0.65; //this is the overload value for 5A at approx 0.13V per amp of output current const int inApin = 39; // INA: Clockwise input const int inBpin =40; // INB: Counter-clockwise input const int pwmpin = 8; // PWM OUTput const int actuatorPin = A3; // the pin that the actuator potentiometer is attached to const int cspin = A9; // Connect to the CS (current sense) pin on the MiniMonsterMoto // Generally, you should use "unsigned long" for variables that hold time // The value will quickly become too large for an int to store unsigned long previousMillis = 0; // will store last time LED was updated unsigned int AirSpeedConvert; // constants won't change: const long interval = 100; // interval at which to move the actuator (milliseconds) void setup() { DcsBios::setup(); pinMode(inApin, OUTPUT); pinMode(inBpin, OUTPUT); pinMode(pwmpin, OUTPUT); pinMode(cspin, INPUT); pinMode(actuatorPin, INPUT); } void onAirspeedgaugeChange(unsigned int newValue) { AirSpeedConvert = newValue; //Read the airspeed value } void AirspeedChange() { int actuatorPosNow = analogRead(actuatorPin);// read the Actuator potentiometer (this will be a value between 132 and 1020 see above) int AIRSPEED = static_cast<int>((AirSpeedConvert/46.17)+132); //see explanation for this factor above, will change for different actuators if (AIRSPEED > actuatorPosNow+10){ //if AIRSPEED is higher, start forward motion digitalWrite(inApin, HIGH); //Direction Forward analogWrite(pwmpin, 255); //set PWM speed to max. delay(200); motorOff(); } else if (AIRSPEED < actuatorPosNow-10) { //if AIRSPEED is lower, start Reverse motion digitalWrite(inBpin, HIGH); //Direction Reverse analogWrite(pwmpin, 255); //set PWM speed to max. delay(200); motorOff(); } else { //if AIRSPEED is same as actuator position, switch motor off motorOff(); } if((analogRead(cspin)>CS_THRESHOLD)); { motorOff(); } } DcsBios::IntegerBuffer airspeedgaugeBuffer(0x5436, 0xffff, 0, onAirspeedgaugeChange); void motorOff() { digitalWrite(inApin, LOW); digitalWrite(inBpin, LOW); analogWrite(pwmpin, 0); } void loop() { DcsBios::loop(); // we will check the satus of airspeed every second unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { //check if more than 1/10th second has passed previousMillis = currentMillis; // if yes, save the last time you moved the actuator AirspeedChange(); // and run the Airspeedchange function } // else nothing, just carry on.. } Link to comment Share on other sites More sharing options...
Stevo_HR Posted May 29, 2020 Share Posted May 29, 2020 (edited) Thanks for sharing that Shredder. I believe this thread might be just what I have been looking for to help me create some kind of haptic feedback device for DCS. I have been been looking everywhere for some way to read info about FF(vibration only) or induce that vibration with lua but I now realise I missed a trick there. Instead I can get data from the aircraft's current state (thanks to [FSF]Ian) and with your code as a guide drive whatever H/W I decide to use. I am new to all this but excited at all the possibilities! Edited May 29, 2020 by Stevo_HR improved grammar slightly :lol: Link to comment Share on other sites More sharing options...
shreddersa Posted May 29, 2020 Author Share Posted May 29, 2020 (edited) Thanks for sharing that Shredder. I believe this thread might be just what I have been looking for to help me create some kind of haptic feedback device for DCS. I have been been looking everywhere for some way to read info about FF(vibration only) or induce that vibration with lua but I now realise I missed a trick there. Instead I can get data from the aircraft's current state (thanks to [FSF]Ian) and with your code as a guide drive whatever H/W I decide to use. I am new to all this but excited at all the possibilities! Indeed Stevo! You are most welcome. :) More on the force feedback system I have implemented here: Heritage Flight Simulation Spitfire Mk.IX Edited May 29, 2020 by shreddersa Added info Link to comment Share on other sites More sharing options...
Recommended Posts