TigersharkBAS Posted July 15, 2014 Posted July 15, 2014 (edited) The contents of this thread will eventually make it into the Wiki I started with Devon Custard but during the process of experimentation and for discussion purposes I have started a thread to explain the steps and process I will go through to get this going. My goal is to make a working Caution Light Panel using an Arduino Uno Ethernet variant and have DCS send data to it over the LAN (using UDP). I want this because I want to avoid the "middle man" code that so many have written to glue an Arduino to DCS. There are pros and cons to both approaches for what it is worth, this thread will capture the journey down the Ethernet only and no middle man code approach. Here is a video showing the early stages of progress. Components: Arduino Uno Arduino Uno Ethernet Shield Adafruit NeoPixel Shield Edited July 15, 2014 by TigersharkBAS 3 [sIGPIC][/sIGPIC] Creator of: F-18C VFA-195 "Dambusters" 1998 CAG Livery https://forums.eagle.ru/showthread.php?t=213788 F-18C VFA-195 "Dambusters" July 2001 CAG Livery https://forums.eagle.ru/showthread.php?t=215950 Pilot avatars for DCS Logbook https://forums.eagle.ru/showthread.php?t=221160 How to make a DCS A-10C Panel http://forums.eagle.ru/showthread.php?t=65998
Hansolo Posted July 16, 2014 Posted July 16, 2014 Excellent, TigersharkBAS :thumbup: I am really looking forward to reading more in this as I would like to go down the same path. My Arduino code skills are limited and the C# are non existing. Therefore it would be very intersting as you mention yourself, to avoid the "middle man". Which Ethernet shield are you using, W5100? I got a Uno with W5100 that I had been using for Gremlins CMSP export, which also uses UDP. But have gotten stuck on how to handle the string from the export. This is really going to be interesting. Thanks a lot for sharing :thumbup: And subscribed Cheers Hans 132nd Virtual Wing homepage & 132nd Virtual Wing YouTube channel My DCS-BIOS sketches & Cockpit Album
TigersharkBAS Posted July 16, 2014 Author Posted July 16, 2014 Thanks HMA. Yes. I am using the 5100. I will post the provisional (and unfinished) code later tonight when I get home. It isn't very complicated. Basically, I have used some of Devon Custard's work and modified an export.lua file that exports only the Master Caution and Caution Panel lights. It sends the status of all of these in a single string like this (lets assume 404 is master caution light and 405 is Seat Not Armed for this example) *404-1.0:405-1.0# The '*' means the string is beginning. The "-" separates a command (master caution) from a value (1.0 meaning ON). The ":" means a new command/value pair and the "#" means end of UDP message. I pick apart this string sequentially using some simple code I will post. Then pass each command/value pair to a case statement that turns on the appropriate light. This does require some more experimentation though. In the example in the video I was only sending 2 values from DCS to the Arduino. The Master Caution light and the Seat Not Armed light. Peformance was great. After making the video I enriched the export.lua to send a string with 13 lights. This caused a delay of about 2-3 seconds between unarming the seat and the Arduino lights activating. So the next experiment for me is to see whether it is better peformance wise to send a large string from DCS or to simply send each command/value in succession to the Arduino. I am almost certain it is the Arduino causing the bottleneck as it iterates through the string. Perhaps just being sent a pair of data in quick succession works better. Also note that the Caution Panel is a matrix of 4x12 lights. Unfortunately the NeoPixel shield will only have 8 rows for me to test with but it gets the ball rolling. Once the DCS to Arduino code is stable and working I will be connecting this to custom made LED matrix using a Max7219 and ditch the NeoPixel shield. [sIGPIC][/sIGPIC] Creator of: F-18C VFA-195 "Dambusters" 1998 CAG Livery https://forums.eagle.ru/showthread.php?t=213788 F-18C VFA-195 "Dambusters" July 2001 CAG Livery https://forums.eagle.ru/showthread.php?t=215950 Pilot avatars for DCS Logbook https://forums.eagle.ru/showthread.php?t=221160 How to make a DCS A-10C Panel http://forums.eagle.ru/showthread.php?t=65998
Hempstead Posted July 16, 2014 Posted July 16, 2014 Excellent! I'd be interested in the UDP protocol, as I am trying to make Hempstick support the SAM4E XPLAINED Pro board, which has Ethernet on it. I have a much bigger plan for the Ethernet with Hempstick and will define a protocol for it as well. But if you have a protocol ready, why not supporting it? Saves me time to write the script bridge software module. BTW, I am not quite sure I understand what you mean by "'*' means the string is beginning, ..., and '#' means end of UDP message." A UDP packet is just one packet... and the payload is just one continuous bytes stream with length indicated by the UDP packet payload length. There is no need to mark beginning and end with special characters. I must have misunderstood something.
TigersharkBAS Posted July 16, 2014 Author Posted July 16, 2014 (edited) IT might become more obvious when I post the code. They are basically markers to let my code know when to stop processing each packet. SOP = Start Of Packet (*) EOP = End Of Packet (#) PAYLOAD = the characters between SOP and EOP PACKET = SOP + PAYLOAD + EOP You might see a better way to do it in which case I am all ears :-) Edited July 16, 2014 by TigersharkBAS [sIGPIC][/sIGPIC] Creator of: F-18C VFA-195 "Dambusters" 1998 CAG Livery https://forums.eagle.ru/showthread.php?t=213788 F-18C VFA-195 "Dambusters" July 2001 CAG Livery https://forums.eagle.ru/showthread.php?t=215950 Pilot avatars for DCS Logbook https://forums.eagle.ru/showthread.php?t=221160 How to make a DCS A-10C Panel http://forums.eagle.ru/showthread.php?t=65998
TigersharkBAS Posted July 16, 2014 Author Posted July 16, 2014 Arduino code can be found here: https://github.com/jvanlint/UFC_CautionPanel Export Lua is as follows. Note this is not a complete set of lights yet. Just the beginnings of a prototype. Only contains 13 lights including the Master Caution. --IP address of the computer that is going to receive this Host="192.168.1.5" --And UDP port that the computer is listening on. Port=8888 --This function is called at the start of every mission function LuaExportStart() --Tell Lua we're going to use sockets package.path = package.path..";.\\LuaSocket\\?.lua" package.cpath = package.cpath..";.\\LuaSocket\\?.dll" --define the socket class socket=require("socket") --create the socket we're going to use throughout the script c=socket.udp() c:setsockname("*",0) c:setoption('broadcast',true) c:settimeout(.001) end --This function is called at the end of every mission function LuaExportStop() c:close() end function LuaExportBeforeNextFrame() end function LuaExportAfterNextFrame() --This function is called every time a simulation frame finishes. We are going to put our export function here --GetDevice(0) returns the main panel from which "MOST" gauges and data can be obtained. local Device = GetDevice(0) --Get the state of 404 which is the master caution lamp local masterCaution = Device:get_argument_value(404) local engineStartCycle = Device:get_argument_value(480) local leftHydPress = Device:get_argument_value(481) local rightHydPress = Device:get_argument_value(482) local gunUnsafe = Device:get_argument_value(483) local antiskid = Device:get_argument_value(484) local leftHydRes = Device:get_argument_value(485) local rightHydRes = Device:get_argument_value(486) local oxyLow = Device:get_argument_value(487) local elevDiseng = Device:get_argument_value(488) local seatNotArmed = Device:get_argument_value(490) local bleedAirleak = Device:get_argument_value(491) local ailDisengage = Device:get_argument_value(492) --Format the data into something a little more usable local packet=string.format("*404-%d:480-%d:481-%d:482-%d:483-%d:484-%d:485-%d:486-%d:487-%d:488-%d:490-%d:491-%d:492-%d#",masterCaution, engineStartCycle, leftHydPress, rightHydPress, gunUnsafe, antiskid, leftHydRes, rightHydRes, oxyLow, elevDiseng, seatNotArmed, bleedAirleak, ailDisengage) --Finally send the data socket.try(c:sendto(packet,Host,Port)) socket.try(c:sendto(packet,"192.168.1.40",12345)) end [sIGPIC][/sIGPIC] Creator of: F-18C VFA-195 "Dambusters" 1998 CAG Livery https://forums.eagle.ru/showthread.php?t=213788 F-18C VFA-195 "Dambusters" July 2001 CAG Livery https://forums.eagle.ru/showthread.php?t=215950 Pilot avatars for DCS Logbook https://forums.eagle.ru/showthread.php?t=221160 How to make a DCS A-10C Panel http://forums.eagle.ru/showthread.php?t=65998
agrasyuk Posted July 16, 2014 Posted July 16, 2014 Thanks for sharing TBAS. Will be following. Anton. My pit build thread . Simple and cheap UFC project
TigersharkBAS Posted July 16, 2014 Author Posted July 16, 2014 Part 2 showing more LEDS working and the slight delay I experience. Part 3 showing that you SHOULD NOT send caution panel light info individually from DCS but stick to the "all commands in one string" method. [sIGPIC][/sIGPIC] Creator of: F-18C VFA-195 "Dambusters" 1998 CAG Livery https://forums.eagle.ru/showthread.php?t=213788 F-18C VFA-195 "Dambusters" July 2001 CAG Livery https://forums.eagle.ru/showthread.php?t=215950 Pilot avatars for DCS Logbook https://forums.eagle.ru/showthread.php?t=221160 How to make a DCS A-10C Panel http://forums.eagle.ru/showthread.php?t=65998
TigersharkBAS Posted July 16, 2014 Author Posted July 16, 2014 So gentlemen....I think this needs to be optimised. I can see 2 possible solutions: 1. Someone better at Lua than me figures out how we can send a string to the Arduino via UDP that only contains only values that are changing. or 2. We figure out a better way to pull apart the string in the Arduino code. I am not quite sure what causes the delay...whether it is the receiving of the string over UDP or the processing of it in the Arduino. Any ideas??? [sIGPIC][/sIGPIC] Creator of: F-18C VFA-195 "Dambusters" 1998 CAG Livery https://forums.eagle.ru/showthread.php?t=213788 F-18C VFA-195 "Dambusters" July 2001 CAG Livery https://forums.eagle.ru/showthread.php?t=215950 Pilot avatars for DCS Logbook https://forums.eagle.ru/showthread.php?t=221160 How to make a DCS A-10C Panel http://forums.eagle.ru/showthread.php?t=65998
Hempstead Posted July 16, 2014 Posted July 16, 2014 Here's the regular C code to receive a UDP datagram. recvlen = recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr, &addrlen); The receiver already knows the length of the payload. Thus, no need to mark the beginning and the end with marker chars... offset 0 is the beginning, offset recvlen - 1 is the last char. With TCP, stream-based socket, you do need to mark the beginning and the end (or send the length as part of the payload), with UDP datagram... no need for that. No big deal, if it helps you parse the string, I can always skip offset 0 and offset recvlen - 1 chars. IT might become more obvious when I post the code. They are basically markers to let my code know when to stop processing each packet. SOP = Start Of Packet (*) EOP = End Of Packet (#) PAYLOAD = the characters between SOP and EOP PACKET = SOP + PAYLOAD + EOP You might see a better way to do it in which case I am all ears :-)
TigersharkBAS Posted July 17, 2014 Author Posted July 17, 2014 OK...that saves 2 cycles of the For loop. We need a better way to process that string though. Or is this as good as it gets? Unfortunately I'm not sure if compressing the string will help as I don't think the problem is receiving the string...it is processing it....I think :helpsmilie: [sIGPIC][/sIGPIC] Creator of: F-18C VFA-195 "Dambusters" 1998 CAG Livery https://forums.eagle.ru/showthread.php?t=213788 F-18C VFA-195 "Dambusters" July 2001 CAG Livery https://forums.eagle.ru/showthread.php?t=215950 Pilot avatars for DCS Logbook https://forums.eagle.ru/showthread.php?t=221160 How to make a DCS A-10C Panel http://forums.eagle.ru/showthread.php?t=65998
Hempstead Posted July 17, 2014 Posted July 17, 2014 OK...that saves 2 cycles of the For loop. We need a better way to process that string though. Or is this as good as it gets? Unfortunately I'm not sure if compressing the string will help as I don't think the problem is receiving the string...it is processing it....I think :helpsmilie: It's a structured data... I would avoid string processing altogether... i.e. design the protocol so that it requires no string processing... particularly, string processing is not the strong suit of embedded processors. What I mean is that the data is a simple name/value pairs. And due to the size limitation of UDP datagram, if you wish to control many devices (or indicators), you have to send multiple datagrams anyway. So, why not do this. 1. Each datagram is for one device only. 2. First 2 bytes is the destination device id (2 bytes gives you 65536 devices, might want to reserve device #0 as the broadcast). 3. The next byte indicate the total number of name/value pairs. 4. each name is 2 bytes, and value is 2 bytes. No parsing is needed. But the receiver decoding code do have to be carefully written so that it doesn't do buffer overrun in case the total number of name/value pairs is maliciously bigger than the actual. This way, you can send more than one value to each devices, and it's a little extendable -- for now, you only have a couple of name/value pairs. 1. Name = 0x0000 (Red) 2. Name = 0x0001 (Green) 3. Name = 0x0002 (Blue) 4. Name = 0x0003 (Brightness, perhaps PWM control of brightness?) And, later on, you can define more attributes to send. Not only that, each device number can have different legal name/value pair definitions.
Hempstead Posted July 17, 2014 Posted July 17, 2014 (edited) Forgot that it will also need the 5th attribute. 5. Name = 0x0004 (LED #). Also, since each name and each value is two bytes, you do have to specify whether it's big endian or little endian... I would go with the network byte order, i.e. big endian. But it doesn't really matter that much, as long as it's specified. Edited July 17, 2014 by Hempstead
TigersharkBAS Posted July 17, 2014 Author Posted July 17, 2014 Hempstead...this is great......but I might need some more practical examples from you. I'm not sure I'll be able to implement what you are talking about. [sIGPIC][/sIGPIC] Creator of: F-18C VFA-195 "Dambusters" 1998 CAG Livery https://forums.eagle.ru/showthread.php?t=213788 F-18C VFA-195 "Dambusters" July 2001 CAG Livery https://forums.eagle.ru/showthread.php?t=215950 Pilot avatars for DCS Logbook https://forums.eagle.ru/showthread.php?t=221160 How to make a DCS A-10C Panel http://forums.eagle.ru/showthread.php?t=65998
Hempstead Posted July 17, 2014 Posted July 17, 2014 Hempstead...this is great......but I might need some more practical examples from you. I'm not sure I'll be able to implement what you are talking about. Ok. say we define the format as the following struct. Note that, these are pseudo code to demonstrate the concept, so forgive me for the possible syntax errors; I ain't no compiler. #define DEVICE_NET_TARGET_DEVICE_LED 0x0001 #define DEVICE_NET_DEVICE_LED_ATTR_R 0x0000 #define DEVICE_NET_DEVICE_LED_ATTR_G 0x0001 #define DEVICE_NET_DEVICE_LED_ATTR_B 0x0002 #define DEVICE_NET_DEVICE_LED_ATTR_INTENSITY 0x0003 #define DEVICE_NET_DEVICE_LED_ATTR_NUM 0x0004 struct { uint_16_t name, uint_16_t value, } attribute; struct { uint16_t target_device, uint8_t num_attrs, attribute *attributes } device_datagram; Then, a device_datagram example would look like this. {DEVICE_NET_TARGET_DEVICE_LED, 0x0005, DEVICE_NET_DEVICE_LED_ATTR_R, 0x0000, DEVICE_NET_DEVICE_LED_ATTR_G, 0x00CA, DEVICE_NET_DEVICE_LED_ATTR_B, 0x00FE, DEVICE_NET_DEVICE_LED_ATTR_INTENSITY, 0x8888, DEVICE_NET_DEVICE_LED_ATTR_NUM, 0x0000} or translated to all hex without symbols. {{0x0001, 0x0005, 0x0000, 0x0000, 0x0001, 0x00CA, 0x0002, 0x00FE, 0x0003, 0x8888, 0x0004, 0x0000} Meaning, the target device control is LED control, and give me the color 0x00CAFE for LED # 0, with 1/2 intensity. So, the processing loops becomes something like this (assuming network byte order and the machine is big endian to simplify the pseudo code). len = recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr, &addrlen); if(len > 0) { device_datagram data_gram = (device_datagram)buf; target_num = data_gram->target_device; uint8_t num_attrs = data_gram->num_attrs; for(uint8_t i = 0; i < num_attrs /* && needs to guard against buf overrun here */; i++) { uint16_t current_attr_name = data_gram->attrs[i].name; // needs to store these to somewhere or use them immediately. uint16_t current_attr_value = data_gram->attrs[i].value; } switch(target_num) { case DEVICE_NET_TARGET_DEVICE_LED: // do something with the stored attrs against LEDs. break; /* to support more devices, just add more cases here. */ default: printf("Unsupported device num = %d, damn it, are you trying to crash me?\n", target_num); break; } } See? No string parsing nor scanning. Just go take the data out.
Hempstead Posted July 17, 2014 Posted July 17, 2014 The trouble with this protocol is that you can only send uint16_t integers over. You can't send anything else. To be able to send something else, you'd need to extend this and add encoding, like string type, int type, float type, double type, etc. etc.
TigersharkBAS Posted July 18, 2014 Author Posted July 18, 2014 Man...this be some heavy duty shit Hempstead. And whilst I might be able to figure out the Arduino code the Lua part escapes me. [sIGPIC][/sIGPIC] Creator of: F-18C VFA-195 "Dambusters" 1998 CAG Livery https://forums.eagle.ru/showthread.php?t=213788 F-18C VFA-195 "Dambusters" July 2001 CAG Livery https://forums.eagle.ru/showthread.php?t=215950 Pilot avatars for DCS Logbook https://forums.eagle.ru/showthread.php?t=221160 How to make a DCS A-10C Panel http://forums.eagle.ru/showthread.php?t=65998
cefs Posted July 18, 2014 Posted July 18, 2014 You could use a typedefed struct and cast a pointer of that type to your buffer, easiest way as long as the structure of your data does not change. Could also use an id, value pair, where the id of the value is used in a switch statement, I have used this before and it works ok, like below- BYTE *b; // pointer to buffer short id; // id of value short numVals; // the number of id, value pairs in buffer, first item in buffer int iVal; // integer value - maybe a frequency short sVal; // short value - maybe airspeed etc b = buffer; // buffer received from sim numVals = (short*)b; // get the number of id, value pairs to process b += sizeof(short); // increment buffer pointer to start of data for( int i = 0; i < numVals; i++) { id = (short*)buffer; b += sizeof(short); // increment buffer pointer to value switch(id){ case 1: // int - maybe a frequency ival = (int*)b; // do something with iVal b += sizeof(int); // increment buffer pointer to next id break; case 2: // short - something like airspeed sval = (short*)b; // do something with sVal b += sizeof(short); break; case 3: ... } }
Hempstead Posted July 18, 2014 Posted July 18, 2014 (edited) Man...this be some heavy duty shit Hempstead. And whilst I might be able to figure out the Arduino code the Lua part escapes me. I don't know nothing about Lua. But the thing is... nobody says you have to implement the full capability of what the protocol can do. Do just the LED part. You can cheat while still conforming to the protocol. ;-) Let's say, you just want to turn LEDs on and off, with no control of intensity with PWM. NeoPixels won't let you do PWM control anyway. So, your first byte will always be 0x0001. 2nd byte will be the 0x0004, then send the 4 attributes (not 5!). Each pair will be 4 bytes. The order of attributes don't matter, but let's simplify it further by fixing the order, and still conforming to the protocol. 1st pairs is always R attribute. 1st byte is always 0x0000, 2nd is always 0xFFFF to turn it on, 0x0000 to turn it off. 2nd attr and 3rd are similar. 4th attr has the first byte always be 0x0004, 2nd byte is the LED number you wish to control. No need to send intensity attr. You can cheat even further, by getting a fixed byte buffer with the following 2 byte arrays. {0x0001, 0x0004, 0x0000, 0xFFFF, 0x0001, 0xFFFF, 0x0002, 0xFFFF, 0x0004, 0x0000} // the on datagram {0x0001, 0x0004, 0x0000, 0xFFFF, 0x0001, 0xFFFF, 0x0002, 0xFFFF, 0x0004, 0x0000} // the off datagram Now, to turn an LED on, take the on datagram, and modify byte 10, with the LED #. And then send the whole datagram over. Repeat this for every LED you wish to control. To turn off an LED, take the off datagram modify byte 10.... In essence, you cheat by taking advantage of the fixed format of only the functions you wish to implement, i.e. only LEDs, by using two template datagram. Well, the protocol is capable of much more, but you only implement what you need, and claim done for only the LED control. Edited July 18, 2014 by Hempstead
Hempstead Posted July 18, 2014 Posted July 18, 2014 (edited) For future proof, I would change the protocol to prepare for the possibility of sending other types of values other than uint16_t by changing the attribute struct as the following. struct { uint_16_t name, uint8_t value_type; uint16_t value_len; // in bytes. char* value, } attribute; Then, of course, we'd need to change the processing code accordingly, but currently implement only value_type 0x00, i.e. uint16_t, and ignore everything else for now. Meaning, the C code on the server side (C++ in the Arduino case) completely ignores the value_type and value_len for now and assumes the value is of type uint16_t by casting it to uint16_t. (The safer way is to check if the value_type is 0x0000, i.e. uint16_t. If not, ignore it, so that if a newer version of client sends the a datagram with other value_types to an older version of server that does not support other value_type, it won't crash the server. Speaking of that, it's probably safer to put a protocol version at the very beginning of the protocol. But it's not really critical to have; just that I would sleep better. ; -). For full implementation of other types, it's best handled with union, etc. But no need to do that now. Then, the Lua datagram templates for on/off need add 3 more bytes for each attr, but these 3 bytes are always fixed for your LED control anyway. That is, we put in the provision for the future, in case we need to send other types, like string or floating points. But we don't implement them now. And implement only uint16_t type. And, if we do implement other types in the future, it's backward compatible so the existing client code don't need to change. Edited July 18, 2014 by Hempstead
Alterscape Posted July 20, 2014 Posted July 20, 2014 Finished reading page one, flipped to page two about ready to describe more or less what Hempstead described, although less sophisticated. Read Hempstead's post, learned some things that should have been obvious about protocol design. Thanks for the thoughtful posts, Hempstead!
smirkza Posted July 22, 2014 Posted July 22, 2014 Hey TigersharkBAS - great work so far! I have a quick question for you reguarding the wiki post you made here - Connecting DCS to Arduino I have gone through all of the steps (even copied and pasted the code from the updated version like you said o at the bottom, but I keep getting an error when trying to connect to DCS. (The test harness worked fine and connected to Arduino). The error that comes up is - System.ArgumentOutOfRangeException: startIndex cannot be larger than length of string. Parameter name: startIndex at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean fAlwaysCopy) at System.String.Substring(Int32 startIndex) at UDPBridge.Form1.ProcessData(String data) in c:\Users\shaun\Documents\Visual Studio 2013\Projects\UDPBridge\UDPBridge\Form1.cs:line 119 at UDPBridge.Form1.buttonUDPON_Click(Object sender, EventArgs e) in c:\Users\shaun\Documents\Visual Studio 2013\Projects\UDPBridge\UDPBridge\Form1.cs:line 46 Any ideas on how I can fix this? :cry: Cheers! Smirks PS - Here is my UDP code (copied straight fro the github post) using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Net; using System.Net.Sockets; using System.IO.Ports; using System.Threading; namespace UDPBridge { public partial class Form1 : Form { private bool done = true; private int listenPort = 65002; public Form1() { InitializeComponent(); } 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(); Thread.Sleep(500); } } catch (Exception ex) { textBox1.AppendText(ex.ToString()); } listener.Close(); } private void buttonUDPOFF_Click(object sender, EventArgs e) { done = true; } private void buttonCOMON_Click(object sender, EventArgs e) { string[] ports = SerialPort.GetPortNames(); string query = "*9999-0#"; foreach (string port in ports) { SerialPort p = new SerialPort(); p.BaudRate = 9600; p.PortName = port; try { p.Open(); if (p.IsOpen) { p.Write(query); string s; Thread.Sleep(500); s = p.ReadExisting(); p.Close(); try { if (s.Contains("<ident:")) { int i = s.IndexOf("<ident:"); s = s.Substring(i + 7); i = s.IndexOf(">"); s = s.Substring(0, i); if (s == "BORIS") { serialPort1.PortName = port; serialPort1.Open(); } } } catch { } } } catch (Exception ex) { ; } } } private void buttonCOMOFF_Click(object sender, EventArgs e) { if (serialPort1.IsOpen) serialPort1.Close(); } private void ProcessData(string data) { data = data.Substring(9); string[] d2 = data.Split('='); if (d2.Length != 2) return; if (d2[1].Substring(d2[1].Length - 1) == "\n") d2[1] = d2[1].Substring(0, d2[1].Length - 1); switch (d2[0]) { //Master Caution Switch case "404": SendSerialData("404", d2[1].ToString()); break; default: break; } } private void SendSerialData(string function, string value) { if (serialPort1.IsOpen) { string sendthis = "*" + function + "-" + value + "#"; char[] c = sendthis.ToCharArray(); serialPort1.Write(c, 0, c.Length); } } } } Cheers, Smirkza
TigersharkBAS Posted July 22, 2014 Author Posted July 22, 2014 Hey smirkza. DevonCustard wrote that article (I am no C# sharp expert). I'll alert him to this post and see if he can help. [sIGPIC][/sIGPIC] Creator of: F-18C VFA-195 "Dambusters" 1998 CAG Livery https://forums.eagle.ru/showthread.php?t=213788 F-18C VFA-195 "Dambusters" July 2001 CAG Livery https://forums.eagle.ru/showthread.php?t=215950 Pilot avatars for DCS Logbook https://forums.eagle.ru/showthread.php?t=221160 How to make a DCS A-10C Panel http://forums.eagle.ru/showthread.php?t=65998
smirkza Posted July 22, 2014 Posted July 22, 2014 Superb, thanks TigerShark! I'm actually going through his forum post now (only just found it) although I've reached a stumbling block when trying his shortened caution light blinky. Getting errors galore when trying to change things as he suggest... This is bugging me as I can handle the arduino fine, but it's all the PC based stuff that's getting to me. If only there was a simple, stand alone program that sent data out to arduinos for you, life would be great! Back to the testing! :thumbup: Cheers, Smirkza
TigersharkBAS Posted July 22, 2014 Author Posted July 22, 2014 try here: http://forums.eagle.ru/showthread.php?t=120386 [sIGPIC][/sIGPIC] Creator of: F-18C VFA-195 "Dambusters" 1998 CAG Livery https://forums.eagle.ru/showthread.php?t=213788 F-18C VFA-195 "Dambusters" July 2001 CAG Livery https://forums.eagle.ru/showthread.php?t=215950 Pilot avatars for DCS Logbook https://forums.eagle.ru/showthread.php?t=221160 How to make a DCS A-10C Panel http://forums.eagle.ru/showthread.php?t=65998
Recommended Posts