Devon Custard Posted January 17, 2014 Posted January 17, 2014 (edited) Ok as requested by a number of people heres my little guide (part 1 anyway) on ONE way to export some of data on the radio panels out of DCS onto some 7 segment LEDs. Why? Just because i wanted to try it :) Firstly, im standing on the shoulder of giants, a lot of what im going to talk about has already been done and explained in depth on this forum. Im just bundling it all together and explaining how it links up.. If at any point i tread on someones toes i apologise, let me know and ill amend the post. Second lets explain how we are going to do it. 1. Exporting the data from DCS. The data that drives whatever instrument panels you are building needs to come from somewhere. Its coming from DCS but to use it you need to get it out and in a usable format. We're going to use HELIOS to deliver that. 2. Modify your data into something that your Arduino sketch can work with. I dont want to do too much coding on the arduino platform so im going to use my desktop (or another if needs be) to model/map any data. DCS exports data that needs to be translated to realworld values. In some cases we are translating switch positions to numerical data. Also this application needs to be able to listen on a UDP port for this data and transmit it out over serial. 3. Connect an arduino and write a simple sketch (code) to receive the data being received over the serial interface. Convert that data to electronic outputs (the LEDs). 4. Validate the data on your LEDs. Mk 1 Eyeball. Existing software/interface already exists, you shouldnt need to change this :) Step 1. Install HELIOS. Get it from here http://www.gadrocsworkshop.com/helios/. Run the setup. Open the profile editor. Click Profile Add interface Select DCS A10c. When the DCS A10C interface window opens, find the A-10 Setup section and click on Setup DCS A-10C This has now created an export.lua file on your file system. For me (Windows 8.1) its in this folder C:\Users\Joe\Saved Games\DCS\Scripts Open the export.lua in a text editor (I use Notepad++ http://notepad-plus-plus.org/download/v6.5.3.html - it has native lua support and will do syntax highlighting, but you can use notepad if you want) This file is the heart of the HELIOS app, it collates a huge amount of data from DCS and formats it for you. Then it sends it out as a UDP packet to a specific IP Address and Port endpoint. We are going to be incredibly cheeky and hitch hike on back of this wonderful script. Navigate to the bottom of the file and find this bit of code function FlushData() if #gSendStrings > 0 then local packet = gSimID .. table.concat(gSendStrings, ":") .. "\n" socket.try(c:sendto(packet, gHost, gPort)) gSendStrings = {} gPacketSize = 0 end end Add this line after socket.try..... socket.try(c:sendto(packet,gHost,65002)) so that it looks like this. function FlushData() if #gSendStrings > 0 then local packet = gSimID .. table.concat(gSendStrings, ":") .. "\n" socket.try(c:sendto(packet, gHost, gPort)) socket.try(c:sendto(packet,gHost,65002)) gSendStrings = {} gPacketSize = 0 end end Now save the file. ( If you want to send this to another server, change gHost in the 2nd socket.try to socket.try(c:sendto(packet,"192.168.1.5",65002)) Change the ip address to the one you want to send it to. When you start DCS and fly a mission you are now streaming 2 sets of data. One to HELIOS on port 9089, and another to port 65002. *CAVEAT* If you click that Setup DCS A10C button again it will rewrite your export.lua and you'll lose your changes so just remember to update it. You could follow the advice to use the 3rd party scripts function but for the life of me i couldnt get it to reliably work as everytime i used it HELIOS functionality would stop working and this is much easier and quicker for new starters. 2. OK next, lets create a UDP listener application. This is NOT hard, well not if you have someone to tell you how to do it :) First if you dont have Visual Studio, lets download it. Its free. http://www.visualstudio.com/downloads/download-visual-studio-vs#d-express-windows-desktop Install and run it. Select new project In the New Project dialog, select Visual C#\Windows from the Templates tree, and Windows Forms Application Enter a name, I called mine UDPListener (WindowsApplication1 isnt very catchy is it? Click OK. Click Toolbox label Click on the pin, it fixes the flyout window. In the form designer, resize the form dialog. Double its size. Do this by dragging one of the forms edges. In the toolbox click on All Windows Forms Scroll down until you find Textbox Click and drag onto the Form designer, should look like this On the right hand side is the Properties dialog. Click on the textbox you dragged onto the form. The context of the properties dialog changes to textBox1 Using the scrollbar dragdown until you find the Multiline entry. HINT there is a little button icon that allows you to sort all the properties Alphabetically. Look under the letter B in textBox. Click on False, a dropdown arrow appears, click on it. Select True. Your textbox changed slightly, it now has drag points on the corners Click the bottom right dragpoint and resize the textbox to half the forms width and height Ok now find Button in the toolbox and drop it on the form as well. Add three more buttons please. Click on each button in turn, and in the properties window find (name) if you sorted the list its at the top. Click on button1 and change it to buttonUDPON Now find the Text Property and set it to UDP ON. Your button has now changed to something a little more friendly. By amending the (Name) and Text properties do the following. Change button2 to buttonUDPOFF - UDP OFF Change button3 to buttonCOMON - COM ON and finally button4 to buttonCOMOFF - COM OFF UDP OFF and COM OFF wont fit on the buttonso resize them a touch until the text appears. Underneath the buttoms add another textbox, set the multiline option and resize it. Finally find SerialPort on the toolbox, its in the Components section. Drag that onto the form. You will see serialPort1 appear at the bottom of the form designer. Should look something like this.... In the Form Designer double click on Form1. The editor opens. Add the following lines (c# code is case sensitive so make sure you copy exactly) Under Form1() also added the following code private void SendSerialData(string function, string value) { if (COM) { string sendthis = "*" + function + "-" + value + "#"; char[] c = sendthis.ToCharArray(); serialPort1.Write(c, 0, c.Length); } } private void ProcessData( string data) { string[] d2 = data.Split( '='); if (d2.Length != 2) return; switch (d2[0]) { case "2251": // textBoxILS.Text = d2[1].ToString(); switch (d2[1].ToString().Substring(0, 3)) { case "0.0": SendSerialData( "101", "108" ); break; case "0.1": SendSerialData( "101", "109" ); break; case "0.2": SendSerialData( "101", "110" ); break; case "0.3": SendSerialData( "101", "111" ); break; default: break; } break; default: break; } } Click on the Form1.cs(design) tab at the top. Double click on UDP ON - this auto generate the click event for the button and open the code editor again. Add the following code so it looks like this. private void buttonUDPON_Click( object sender, EventArgs e) { done = false; UdpClient listener = new UdpClient(listenPort); IPEndPoint groupEP = new IPEndPoint (IPAddress .Any, listenPort); string received_data; byte[] receive_byte_array; try { while (!done) { receive_byte_array = listener.Receive( ref groupEP); received_data = Encoding.ASCII.GetString(receive_byte_array, 0, receive_byte_array.Length); if (received_data.Length > 0) textBox1.Text = ""; string[] r = received_data.Split( ':'); foreach ( string s in r) { ProcessData(s); textBox1.Text += s + Environment.NewLine; } Application.DoEvents(); } } catch ( Exception ex) { textBox1.AppendText(ex.ToString()); } listener.Close(); } Go back to the form editor and double click on the UDP OFF button to generate the click event. This one is easy. Add this line done = true; Ok this ends part 1, but wait we want to see this in action dont we? To test this start DCS, launch a mission - i normally sit on the tarmac in campaign mode. Once the game is running goto your VS session and click the green arrow. That will compile your code into a debug version. The form will open, click on UDP ON. All going well you're now receving a UDP stream direct from DCS!!! In part 2 i'll expand your app to use a serial port to communicate with your arduino(assuming you have one!)UDPListener.zipDCS_OUTPUT_TO_MULTIPLE_7SEG.zip Edited January 26, 2014 by Devon Custard 4
Jimbo Posted January 18, 2014 Posted January 18, 2014 Thanks DC, that's a wonderfully detailed explanation of a lot of the basics - certainly helps someone like me who hasn't a clue on the coding front.... ok.. heading out to find myself an Arduino board :)
Duckling Posted January 18, 2014 Posted January 18, 2014 Thanks DC for taking the time to make this tutorial, greatly appriciated. Cheers Gus - - - -
Milli Posted January 18, 2014 Posted January 18, 2014 Thank you Devon Custard. Very good. Regards, Milli
Elnocho3 Posted January 19, 2014 Posted January 19, 2014 A great and much needed tutorial, nice one! PC spec: i9 9900KS @ 5.1ghz, 32GB RAM, 2 TB NVME M2, RTX 3090 Peripherals: TM Warthog, Saitek Pro Flight Pedals, Rift S, Custom UFC
MacFevre Posted January 19, 2014 Posted January 19, 2014 You sir, are my hero! Thank you! Buttons aren't toys! :smilewink: My new Version 2 Pit: MacFevre A-10C SimPit V2 My first pit thread: A-10C Simulator Pit "The TARDIS." Dzus Fastener tutorial, on the inexpensive side: DIY Dzus Fastener
Devon Custard Posted January 20, 2014 Author Posted January 20, 2014 My pleasure :D Should have the second part done this week, just need to finish the circuit diagram for the Arduino,.
Hansolo Posted January 20, 2014 Posted January 20, 2014 Very nice DC. Thanks for the write up. Very informative and I am looking forward for more info. A very small comment. Instead of writtting a listner this one works very nice http://udp-test-tool.software.informer.com/ A small question. Is there any special reason for transmiting via serial to the Arduino? I would imagine that using a Ethernet shield on the Arduino is much easier. Really looking forward for the next write up from you :thumbup: All the best Hans 132nd Virtual Wing homepage & 132nd Virtual Wing YouTube channel My DCS-BIOS sketches & Cockpit Album
Devon Custard Posted January 20, 2014 Author Posted January 20, 2014 Thanks HMA, always appreciate comments :) Why writing a UDP listener? Like i said its only one way to do it, there are many others. But my reasons for doing it this way were... 1. No experience with writing UDP code on the arduino. But plenty in C# 2. The arduino comes with a USB interface which provides serial comms already. The serial monitor is easier to use to debug (for me at this point, purely because im still learning the arduino) 3. More component = more cost. 4. Im probably going to run more than one board. At which point i might switch over to Gadrocs EOS bus if he has the libraries to drive 7 seg / alpha numeric displays. Either way using one UDP listener means im putting less strain on the lua scripting engine. I reckon my C# will outperform the lua script as i can multi thread if i need to. 4. lastly but more importantly, I want to translate the exported values on my pc which has spare processing capacity and memory plus its a damn site faster. The arduino is purely a driver to my instruments. I havent hit the arduino limits yet but i reckon i will at some point. To be honest in about 6 months i might just rewrite this all and go ethernet shield but im still a n00b. I only started this over the Xmas holidays ( not the coding tho :))
Hansolo Posted January 20, 2014 Posted January 20, 2014 Hi DC, Makes sense. I am just close to running out of USB (14 pieces I think), plus I have absolutely no C# skills and my Arduino skills are limited. Looking forward to more on this thread :thumbup: Oh yeah and subscribed :smilewink: Cheers Hans 132nd Virtual Wing homepage & 132nd Virtual Wing YouTube channel My DCS-BIOS sketches & Cockpit Album
Devon Custard Posted January 20, 2014 Author Posted January 20, 2014 (edited) Part 2 !!! First we start with a pretty diagram. I hope you have lots of tinned wire :music_whistling: If that has frightened you off nothing will. Facepalm moment. :doh: Thats actually a 74HC595 not a 75HC595...... and i missed a ground link from the LED CCpin to the 5v ground. List of parts you will need. 1 metric ton of equipment in various colours - I jest its only 500 kilos worth 2 x 74HCF4511. Actually there are many 4511 chips out there. I just know this one worked. 1 x 74HC595 Apparently this chip is a classic. And before anyone bitches about the limited amount of current it can sink ahhah i have a cunning plan. 14 x 100R Resistors ( 5v supply. Each LED has a 2.5V forward voltage and 25mA so the gurus behind the led resistance calculator tell that a 100R/Ohm resistor will do the job) 2 x 7 Segment LED display of the Common Cathode variety. CAVEAT: My resistor choice is based on the specs of my LED display, you need to verify calcs for whatever you buy. Any questions just ask., Or use this....http://led.linear1.org/1led.wiz Also i deliberately havent shown the full wiring for the LED displays. Simply because i dont know what youre going to use. However its a damn good bet that you will have seven pins a-f, 1 pin called DP and 2 pins called CC or common anode. Pins 1-7 should be matched a-g i.e. 1-a 2-b etc. Ignore DP (decimal point) as the BCD wont use it. Finally CC needs to be wired to the ground of the external 5v supply (not the arduinos grd) Each segment is a LED in its own right so calculate resistance per segment and put the resistor in front of the led segment. Dont be cheap and place it on the cathode. Go and wire that up. Note the 5V supply thats wired to GRD and VCC pins of the 4511 chips (pins 8 and 16). Thats a seperate power line thats wired to a 5v adaptor (4 x 1.5 batteries in series will do that job). The reason im doing this is the the arduino can only drive so much current before it will blow :helpsmilie: Driving the BCD chips on a seperate loop keeps the power requirements away from the arduino. All you are doing is passing a data signal per pin at little or no current(or so i believe). Once you've wired that up. Upload this sketch #define LATCH_ENABLE 13 #define LATCHPIN 8 #define CLOCKPIN 12 #define DATAPIN 11 int x; byte data; byte led1[10]; byte led2[10]; void setup() { led1[0]=0b00000000; led1[1]=0b00000001; led1[2]=0b00000010; led1[3]=0b00000011; led1[4]=0b00000100; led1[5]=0b00000101; led1[6]=0b00000110; led1[7]=0b00000111; led1[8]=0b00001000; led1[9]=0b00001001; led2[0]=0b00000000; led2[1]=0b00010000; led2[2]=0b00100000; led2[3]=0b00110000; led2[4]=0b01000000; led2[5]=0b01010000; led2[6]=0b01100000; led2[7]=0b01110000; led2[8]=0b10000000; led2[9]=0b10010000; x=0; Serial.begin(9600); pinMode(LATCHPIN,OUTPUT); pinMode(LATCH_ENABLE,OUTPUT); } void loop() { if (x==9) x=0; else x++; data=led1[x]|led2[x]; digitalWrite(LATCH_ENABLE,LOW); digitalWrite(LATCHPIN,LOW); shiftOut(DATAPIN,CLOCKPIN,data); shiftOut(DATAPIN,CLOCKPIN,data); digitalWrite(LATCHPIN,HIGH); digitalWrite(LATCH_ENABLE,HIGH); delay(300); } // the heart of the program void shiftOut(int myDataPin, int myClockPin, byte myDataOut) { // This shifts 8 bits out MSB first, //on the rising edge of the clock, //clock idles low //internal function setup int i=0; int pinState; pinMode(myClockPin, OUTPUT); pinMode(myDataPin, OUTPUT); //clear everything out just in case to //prepare shift register for bit shifting digitalWrite(myDataPin, 0); digitalWrite(myClockPin, 0); //for each bit in the byte myDataOut� //NOTICE THAT WE ARE COUNTING DOWN in our for loop //This means that %00000001 or "1" will go through such //that it will be pin Q0 that lights. for (i=7; i>=0; i--) { digitalWrite(myClockPin, 0); //if the value passed to myDataOut and a bitmask result // true then... so if we are at i=6 and our value is // %11010100 it would the code compares it to %01000000 // and proceeds to set pinState to 1. if ( myDataOut & (1<<i) ) { pinState= 1; } else { pinState= 0; } //Sets the pin to HIGH or LOW depending on pinState digitalWrite(myDataPin, pinState); //register shifts bits on upstroke of clock pin digitalWrite(myClockPin, 1); //zero the data pin after shift to prevent bleed through digitalWrite(myDataPin, 0); } //stop shifting digitalWrite(myClockPin, 0); } This will drive a simple loop and output 0-9 to both LEDs to test your circuit works. I figure that will keep you busy long enough for me to double check the final bit of code. NEARLY THERE!! Edited January 20, 2014 by Devon Custard 1
Jimbo Posted January 20, 2014 Posted January 20, 2014 aaannnnnd..... I feel like the stupid kid in class :) i'll just sit quietly at the back and hope someone lets me copy their homework! Nice work DC, may take me a while and a bit of googling to decipher that little lot but sterling effort in putting it in a format that's accessible and I can (just about) understand.
Devon Custard Posted January 20, 2014 Author Posted January 20, 2014 Jimbo, i know how you feel. TBH googling was precisely how i conquered this. Dont be afraid to ask, i might not be able to answer clearly (or correctly) but at least someone out there will be able to. A really good place to start is this arduino tutorial http://arduino.cc/en/tutorial/ShiftOut Then read this one http://scuola.arduino.cc/courses/lessons/view/B7xOJzE Dont worry about understanding it at first. Just accept it will work (When wired correctly). Understanding comes later :)
MacFevre Posted January 22, 2014 Posted January 22, 2014 Jimbo, that is not only the funniest thing I've read in a long time, but the truest for me also! :D aaannnnnd..... I feel like the stupid kid in class :) i'll just sit quietly at the back and hope someone lets me copy their homework! Nice work DC, may take me a while and a bit of googling to decipher that little lot but sterling effort in putting it in a format that's accessible and I can (just about) understand. Buttons aren't toys! :smilewink: My new Version 2 Pit: MacFevre A-10C SimPit V2 My first pit thread: A-10C Simulator Pit "The TARDIS." Dzus Fastener tutorial, on the inexpensive side: DIY Dzus Fastener
Devon Custard Posted January 22, 2014 Author Posted January 22, 2014 Jimbo, that is not only the funniest thing I've read in a long time, but the truest for me also! :D How about i post the UFC master caution sketch and circuit? Its kinda simple, one tactile switch with combined led, but anyone can simulate it with a tactile switch and a seperate led.
Jimbo Posted January 22, 2014 Posted January 22, 2014 I've been doing my research (homework!?), and as DC says, it isn't all that complicated. I had a bit of a 'penny drop' moment last night and I hope to have all the components arrive in the post today. So I'll be putting this together over the weekend and I hope that'll help solidify the concepts in my mind. DC - the UFC sketch would be cool also, as it involves a physical input. But please don't burden yourself unnecessarily, us (well, me) intellectually challenged lot will catch up eventually :)
Devon Custard Posted January 22, 2014 Author Posted January 22, 2014 Lol halfway thru a post for the UFC sketch so ill post BOTH. oooh 2 for 1 bargain price :D Really nice to hear about your penny drop moment. If i've managed to help at least one person then the effort was worthwhile. Ill finish my other post and upload the sketches
Devon Custard Posted January 22, 2014 Author Posted January 22, 2014 Ok simple circuit. Take an arduino, wire pin 13 to the anode of an LED with a 100R resistor. Wire the cathode to the arduino's ground. Its one of the most basic arduino circuits there is. This is your master caution LED. I did it with my illuminated tactile switch but thats just an LED on a switch and its a seperate circuit so makes no difference. http://uk.rs-online.com/web/p/tactile-switches/6927005/ Now wire a switch to whatever input board youre using. I always use one of the leo bodnar boards BU0836x for my rapid prototyping. I have a brydling board for the final wire up but the bodnar for testing as its really fricking quick to setup. http://www.leobodnar.com/products/BU0836X/ Map your switch in DCS to the master caution switch on the UFC. Upload this sketch to your arduino... #define LED 13 String command; String value; int start=0; int mid=0; void setup() { Serial.begin(9600); command=""; value=""; pinMode(LED,OUTPUT); } void loop() { if(Serial.available()) { int c=Serial.read(); if (start==1) { if (c=='-') mid=1; else if(c=='#') { ProcessData(); } else if(mid==0) { command=command+char©; } else { value=value+char©; } } else if(c=='*') { start=1; } } } void ProcessData() { switch(command.toInt()) { case 404: if (value=="1.0") digitalWrite(LED,HIGH); else digitalWrite(LED,LOW); break; } mid=0; start=0; command=""; value=""; } Here you can see im reading the inbound serial stream from the USB COM port in loop(). I read the stream until i receive a valid command packet of the *xxx-yyy# format where xxx is the argument and yyy is the value. When i have that i call ProcessData and use a switch statement to run the relevant code. In this case im only interested in argument 404 (master caution state) and depending on the value which is either 1.0 or 0.0 i set the state of the LED pin to go HIGH or LOW which is 5v or 0v. LED on or off. Oh wait i forgot to amend my listener to output the UDP stuff over serial didnt i. Lets do that next. Open the UDP Listener solution in Visual Studio. In the solution explorer, click on Form1.cs, right click and select View code. This brings up the code editor (might already be open depending on how you closed the solution). Find the ProcessData function private void ProcessData( string data) { string[] d2 = data.Split( '='); if (d2.Length != 2) return; switch (d2[0]) { case "2251": // textBoxILS.Text = d2[1].ToString(); switch (d2[1].ToString().Substring(0, 3)) { case "0.0": SendSerialData( "101", "108" ); break; case "0.1": SendSerialData( "101", "109" ); break; case "0.2": SendSerialData( "101", "110" ); break; case "0.3": SendSerialData( "101", "111" ); break; default: break; } break; default: break; } } Change it to private void ProcessData( string data) { string[] d2 = data.Split( '='); if (d2.Length != 2) return; switch (d2[0]) { case "2251": // textBoxILS.Text = d2[1].ToString(); switch (d2[1].ToString().Substring(0, 3)) { case "0.0": SendSerialData( "101", "108" ); break; case "0.1": SendSerialData( "101", "109" ); break; case "0.2": SendSerialData( "101", "110" ); break; case "0.3": SendSerialData( "101", "111" ); break; default: break; } break; case "404": SendSerialData("404",d2[1].ToString(); break; default: break; } } The updated code is in red. Finally open the Form Designer, right click on Form1.cs and select view designer. Click on the serialPort1 (at the bottom of the form) and change the property PortName to the COMx port you are connected to your arduino with. HINT, your sketch editor will tell you at the bottom of the editor Should say Arduino on COMx... If you run the above sketch and the UDP Listener you should be able to trigger a master caution in DCS and see a flashing LED. I normally trigger the boost pumps toggle switch whilst sitting on the tarmac. Pressing my tactile switch turns it off(actually it just stops flashing, sometimes it stays on. I need to write a timer to turn it off when the value doesnt change for a second or two) Hmmm this last part of the guide feels a bit rushed. Ill edit it into something more friendly later this week.
Extranajero Posted January 22, 2014 Posted January 22, 2014 Is there any way to reproduce the same functionality using a lathe and a milling machine rather than witchcraft ? ( sorry, code and microcontrollers ) - I might have a chance then :D Seriously, I'm enjoying this even though it's making my brain hurt. I have an Arduino Uno on order together with several miles of wire and lots of mysterious electric components and will need all the help I can get... --------------------------------------------------------- PC specs:- Intel 386DX, 2mb memory, onboard graphics, 14" 640x480 monitor Modules owned:- Bachem Natter, Cessna 150, Project Pluto, Sopwith Snipe
Devon Custard Posted January 22, 2014 Author Posted January 22, 2014 hahah witchcraft :) Help is here. Im gonna churn out a more complete sketch and version of the Listener this weekend with examples of how to extend it.... After that its just the usual Imagination is just your limiting factor (or someone elses if youre nice to them) Oh and someone was really polite and asked me if i was sharing or selling my sketches/code. Sharing obviously. I plan on asking lots of questions myself and figure least i can do is share my own experience if someone is crazy enough to ask my opinions.
bnepethomas Posted January 23, 2014 Posted January 23, 2014 Nice work on this, its always the first Hello world that is the hardest... well may be the first time the blue smoke escapes from the ICs :)
Devon Custard Posted January 23, 2014 Author Posted January 23, 2014 Having fun translating this from breadboard to prototype matrix board at present. Shift registers playing up which is royally annoying. Plus i find everytime i look at the circuit i find myself saying, "oh why dont i do this instead". :) I put the BCDs in to seperate the power supply and making the wiring to LED easier, but actually i think i just complicated it. I might have a newer vesion of the circuit without the BCDs....... Ah well im having fun....
Devon Custard Posted January 23, 2014 Author Posted January 23, 2014 Ok found the issue, seems using a common latch pin signal doesnt work on the 4511 chips. Will rework the sketch & circuit to use multiple pins, not brilliant but should work until i can resolve why.....
Joe Kurr Posted January 24, 2014 Posted January 24, 2014 I'm working on something similar (see the DFDT Cockpit thread). I have written a small bridge application to make communication between DCS and the Arduino easier. This application simply transfers the data sent from DCS (via UDP) to the Arduino (via RS232) and vice versa. Dutch Flanker Display Team | LLTM 2010 Tiger Spirit Award
Devon Custard Posted January 24, 2014 Author Posted January 24, 2014 Yup, looks pretty much the same.:) Nice
Recommended Posts