Jump to content


ED Beta Testers
  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by FSFIan

  1. If you want dirt cheap and 18 I/O pins are enough, try an Arduino Pro Micro clone for less than $5. Use a Teensy if you actually need the processing power, for example to drive a graphical display.
  2. There are two general approaches to use a microcontroller with DCS. Approach 1: Build a USB HID device and map it in the DCS: World controller options (a) with a microcontroller that has built-in USB support (such as the ATMega32u4 featured on the Arduino Leonardo and Arduino Pro Micro boards) (b) using an Arduino board with a controller that doesn't have USB support, by reprogramming the ATMega16U2 used as a USB-to-serial converter (works on the Uno and Mega 2560 boards; when buying a clone, make sure your board has an ATMega16U2 instead of a dedicated usb-to-serial chip like the CH340) © with a microcontroller that doesn't have built-in USB support, implementing low-speed USB in software (see V-USB) This approach has the advantage that it works with all modules. If a module only has a "toggle" keybind for a certain switch, some editing of Lua files is required to make physical toggle switches behave properly and you'll want to use a tool such as JSGME to re-apply those changes after every DCS update. The main disadvantage is that it does not support output from the sim to a microcontroller, so if you want working caution lights, gauges and (text) displays on your panels you'll have to use the second approach. Approach 2: Use a custom protocol over an (emulated) serial port and interface to DCS through Export.lua By using the Lua scripting interface that DCS: World provides, we can grab all sorts of information from the sim and forward it to a microcontroller to control LEDs, servos, stepper motors, and small LCD or OLED displays. There are three projects I am aware of that use this approach: Helios is not limited to virtual panels -- it also supports talking to physical hardware over the EOS protocol, which is described on Gadroc's website. IIRC an Arduino library is available to help with building your own devices. The DCS to Arcaze Connector talks to panels based on Arcaze USB boards, which are commercial USB I/O boards My own project, DCS-BIOS, also targets Arduino boards
  3. It won't work on the Due, but it should work fine on the Mega 2560 (added on April 5 in this commit).
  4. Usually, the second line should work (as long as all other scripts use it as well). I vaguely remembered that you had problems with UDP before and had to use TCP instead. Found it again with the forum search: link to the german thread Try the connection script from that post (but change the baud rate from 500000 to 250000).
  5. On the DCS-BIOS website you will find a link to the developer guide. It describes how to add an aircraft to DCS-BIOS. It assumes you have at least a basic understanding of the Lua scripting language, so you'll probably have to learn that first.
  6. There are no cockpit arguments for those displays (because they are not implemented as an animation in the 3D model). They are implemented with a different mechanism. As far as I can tell, "indications" are a way for cockpit devices to place graphic elements (including text) on a texture in the cockpit. Export.lua provides the list_indication() function, which takes one integer parameter (might be a cockpit device id?) and returns a string that contains the internal identifier of each indication (such as "txt_mach") and, if the indication is a text element, also the text that is displayed. DCS-BIOS provides the function BIOS.util.parse_indication, which will call list_indication() and return a Lua table that maps the indication IDs to their associated text. Just try out the code snippets I posted in the Lua console. You'll see how it works after playing around for a while and comparing the result of, for example, "return list_indication(0)" to what you see on the HUD in your virtual cockpit.
  7. Look at the output of the list_indication function given different numbers as a parameter. For example, return list_indication(0) results in ----------------------------------------- glass ----------------------------------------- TFOV ----------------------------------------- TFOV2 ----------------------------------------- VTH_center children are { ----------------------------------------- vth_fpm children are { ----------------------------------------- Accel_Z children are { } ----------------------------------------- wp_trackerror_to } } ----------------------------------------- tape_begin ----------------------------------------- tape_hdg ----------------------------------------- tape_end ----------------------------------------- hdg_ind ----------------------------------------- Pitch_Ladder_center children are { ----------------------------------------- pl_p90_line ----------------------------------------- pl_p85_line ----------------------------------------- pl_p80_line ----------------------------------------- pl_p75_line ----------------------------------------- pl_p70_line ----------------------------------------- pl_p65_line ----------------------------------------- pl_p60_line ----------------------------------------- pl_p55_line ----------------------------------------- pl_p50_line ----------------------------------------- pl_p45_line ----------------------------------------- pl_p40_line ----------------------------------------- pl_p35_line ----------------------------------------- pl_p30_line ----------------------------------------- pl_p25_line ----------------------------------------- pl_p20_line ----------------------------------------- pl_p15_line ----------------------------------------- pl_p10_line ----------------------------------------- pl_p05_line ----------------------------------------- pl_hor_line ----------------------------------------- pl_m05_line ----------------------------------------- pl_m10_line ----------------------------------------- pl_m15_line ----------------------------------------- pl_m20_line ----------------------------------------- pl_m25_line ----------------------------------------- pl_m30_line ----------------------------------------- pl_m35_line ----------------------------------------- pl_m40_line ----------------------------------------- pl_m45_line ----------------------------------------- pl_m50_line ----------------------------------------- pl_m55_line ----------------------------------------- pl_m60_line ----------------------------------------- pl_m65_line ----------------------------------------- pl_m70_line ----------------------------------------- pl_m75_line ----------------------------------------- pl_m80_line ----------------------------------------- pl_m85_line ----------------------------------------- pl_m90_line } ----------------------------------------- route_bearing ----------------------------------------- FOV_center ----------------------------------------- txt_asi 425 ----------------------------------------- txt_mach 0.74 ----------------------------------------- txt_balt 74 ----------------------------------------- txt_balt_H 60 ----------------------------------------- wp_dist11NM 24 N 01 which looks like the HUD. Assuming you want the mach number, you can then grab it like this: return BIOS.util.parse_indication(0)["txt_mach"] As far as I can figure it out: list_indication(0): HUD list_indication(1): VTB list_indication(3): ECM (remaining chaff) list_indication(4): ECM (remaining flares) list_indication(5): that display on the right, maybe fuel flow (I have no idea how this aircraft works, but the fly-by-wire system was nice enough to keep me from crashing during testing xD) list_indication(6): displays to the left of the VTB, top row list_indication(7): displays to the left of the VTB, bottom row list_indication(8): displays to the right of the VTB list_indication(9): UHF radio frequencies list_indication(10): right console, top right corner list_indication(11)L right console, the other stuff on the top panel
  8. ClayM: In setup(), change this line: memset(max7219_rows, 0xff, sizeof(max7219_rows)); to this: memset(max7219_rows, 0x00, sizeof(max7219_rows)); I think I added that line at some point during debugging to confirm that all rows and columns are working without having to start DCS. (Removing that line would probably work as well, but it's cleaner to explicitly initialize the contents to zero; otherwise, they will be undefined.)
  9. kadda: If I understand correctly, you don't have real instruments (as in "intended to be installed in a real plane") but real simulator instruments, as in "intended to be installed in a professional simulator". Since these already are designed to be driven by electrical signals (instead of air pressure), you probably won't have to modify their inner workings. You will have to find out how they work and come up with a circuit that allows you to control them from an Arduino (probably using additional ICs such as op amps and DACs). You will also have to add L-39 support to DCS-BIOS. Once DCS-BIOS has L-39 support, you will need to write an Arduino sketch that takes a numeric value that DCS-BIOS provides and translates it into the correct control signals for your instrument. If you want more specific help, it would help to know more about your instruments and your background in programming and electronics.
  10. The number of steps per detent for rotary encoders is currently hard-coded into DCS-BIOS. There is no good reason for that, so I'll add a constructor argument in the next release. Sounds like your encoders use two steps per detent. (There are several bad reasons for hardcoding it: it saves one byte of memory per rotary encoder. When I wrote the thing two years ago, I did anything I could to save RAM because I never actually did the math. I have since figured out that assuming we need half the memory for rx/tx buffers, stack and other housekeeping, a typical Arduino board will have about 10 bytes per GPIO pin. RAM is scarce, but not as scarce as I thought. Another reason is lazyness: if I don't add a feature, I don't have to explain it in the documentation. I knew that encoders with different steps per detent exist -- common values are one, two or four steps per detent --, but every single encoder I had ever seen was of the four steps variety.)
  11. The problem that Warhog is referring to is the following: when the Arduino Mega is started up (or reset), it will look for a new sketch upload on the serial port. Only once it has not received any data for a certain amount of time, it will end the bootloader and start your sketch. So when the connect-serial-port.cmd script is started while DCS is already running, the Mega will be reset and immediately be flooded with data so it will never leave the bootloader. The workaround is to pause DCS, press the reset button on the Mega, wait a few seconds, then unpause DCS. A solution to the problem is to upload the sketch to the Mega with an ISP programmer (such as the USBTinyISP), which removes the bootloader. Curiously, we did not observe this behavior on other Arduino boards; I assume their bootloaders exit when they receive unexpected data. I don't think the bootloader is the (only) problem in this case, because your debug output clearly shows that the RS485Master sketch has started up and is polling the bus. I have no idea why it stops sending anything at all after a few seconds (even if there are errors in the received data, the state machine should time out and continue no matter what). It might even work as intended, but some other error could cause another device (either the Nano or the RS-485 adapter connected to the PC for debugging) to try to drive the bus, thus making anything that is sent unreadable. From what I can tell, the circuit you have built should just work with both jumpers connected. Reasoning about the behavior when a jumper is missing is difficult without knowing the schematic of the RS485 adapter modules. The unconnected pins could be floating, which would lead to undefined behavior. More likely, the pins have pull-up or pull-down resistors connected to them. I found this schematic which allegedly belongs to such a module, and after looking at a few high-res pictures of those modules on eBay I think it is correct. It shows a pull-up resistor connected to both the "driver enable" and the "/receiver enable" lines, which would but the module into TX mode by default (receiver disabled, transmitter enabled). I would be very surprised if anything still worked when removing the jumper on the Nano side. And of course there could still be errors in the actual code, since it hasn't received a lot of testing yet, although I am pretty sure that the two example sketches were one of the things I used to verify functionality. Then there is the possibility of a broken RS-485 module. It's unlikely, but it can happen. Warhog had an entire batch of bad MAX487 chips. A recording of the DE, DI, RE and RO signals for both RS-485 modules would help to narrow this down. You can get cheap 8-channel logic analyzers for less than $10 on eBay. They won't come with any software or documentation, but they work with the open-source sigrok software (http://sigrok.org). This page on the sigrok wiki links to other devices like this.
  12. And I bet they could still be improved a bit for the common case where only a single character changes (cursor blinking, editing the scratchpad). The current code uses a StringBuffer per 24-character line of text, so when a single character changes, the whole line is rewritten. For a graphic CDU display, it would be a good idea to make a variant of the StringBuffer class that tracks changes on a per-character basis instead. According to the ILI9341 datasheet, the controller supports a "set backlight brightness" command. But if the manufacturer of the shield hasn't wired the backlight control up to the ILI9341 chip, that probably won't work. There are a few more backlight-related commands that seem to influence the gamma correction or something, but I have no idea what they do. You can call a StringBuffer's getData() method at any time to get the buffered data (e.g. to get line 0, use "cduLine0Buffer.getData()").
  13. I just spotted a bug in the DEFAULT_SERIAL implementation that can lead to undefined behavior. Try the following sketch, which uses IRQ_SERIAL mode instead. IRQ_SERIAL mode is much better than DEFAULT_SERIAL anyway and should always be used unless your Arduino board features a controller where it doesn't work (something other than the ATMega328 or ATMega2560). #define DCSBIOS_IRQ_SERIAL #include "DcsBios.h" /* paste code snippets from the reference documentation here */ DcsBios::Switch2Pos hydContSwToggle("HYD_CONT_SW", 10); DcsBios::LED clD1(0x1414, 0x2000, 13); void setup() { DcsBios::setup(); } void loop() { DcsBios::loop(); } If that doesn't work, I'll build the circuit and try to reproduce the problem once I get back to my apartment in a few days (I am currently on the train ride to home to eat some delicious cake :P).
  14. To make your toggle switch work properly, use DcsBios::Switch2Pos instead of DcsBios::ActionButton: DcsBios::Switch2Pos hydContSwToggle("HYD_CONT_SW", 10); The ActionButton is meant for using a physical tactile switch to trigger something that is not a push button in the sim (e.g. toggle a toggle switch, or move a dial one step to the left). It sends a command to the sim when the button is pressed and does nothing when it is released. The constant toggling you see is a bug in the ActionButton implementation that was fixed in v0.2.4 of the Arduino library. You should update to the current version (v0.2.5).
  15. Please post your complete sketch.
  16. TigersharkBAS: Which pin does the sketch read for the UFC_1 pin? I think what happened here is the following: you disconnected pins 0 and 1 to avoid the serial RX and TX pins, but the software on the Arduino is still the same (you either forgot to update the code, forgot to upload it again, or did not notice that something went wrong while uploading). Now you push a button. The next call to DcsBios::loop() detects the pin change and ends up calling sendDcsBiosMessage(...) to send a message to the PC. The last character of that message is always a newline character. Now sendDcsBiosMessage() does not wait for the full message to be sent -- it will return as soon as the transmission of that last character has started! So when sendDcsBiosMessage() returns, the UART hardware will start to transmit 00001010 in binary over pin 1 (TX). Because the UART peripheral is independent of the processor, this happens while the program is still running. Because the sketch has not been updated properly, it still thinks there is a button connected to pin 1. If it reads the state of pin 1 at the precise moment that one of the '1' bits of the newline character is being transmitted, it will detect that as a change and send 'UFC_1 1\n' to the PC! This explains why it seems random which buttons are affected -- whether or not a button has this problem depends on the precise amount of time that it takes to get back to checking the button connected to pin 1 after sending the first message. Bonus nitpick question: "But a pushed button results in a logic LOW -- wouldn't it be triggered by a '0' bit transmission?" No, because the UART also represents '1' as LOW and '0' as HIGH :)
  17. I doubt that any of your switches have a bounce time of more than one, let alone 10 milliseconds. Bounce times longer than that exist, but I would only expect them in large toggle switches or big spring-loaded push buttons. I never had bouncing problems with tactile switches. I suspect it's the wiring. Those dupont jumper wires can make bad connections when plugged into the Arduino headers. Sometimes it's a bad wire, sometimes it helps to unplug it and rotate it 90 degrees before plugging it back in. You can get a good continuity test with the multimeter, and then the contact will be interrupted momentarily by the slightest tug on the wire. And those wires easily get wiggled around as a side effect of pushing a button on that breadboard. The dupont wires will connect reliably to a breadboard due to the spring contacts of the breadboard. Identify a working switch (A) and a bouncing switch (B) and then try the following: Swap the tactile push buttons. If the behavior is still the same (A works, B bounces), you know it's not the switch itself. Swap the wires and see what happens. Another way to test for wiggly wire problems: short out all your switches on the breadboard so they are "closed" all the time, then intentionally wiggle all the wires around. If any button presses are registered, you have a loose contact somewhere. Of course, it could still be something in the code, so post your complete sketch just in case (and upload it once more to make extra sure that the Arduino board is running the code you think it is).
  18. Can you post a schematic and/or a picture of your setup?
  19. You can't use pins 0 and 1, those are the serial RX and TX lines. For a primitive but effective debouncing method, just add a small delay to your loop() method (about 10 or 20 milliseconds). Avoiding pins 0 and 1 (and 13 for inputs, as it's connected to the built-in LED) and maybe adding a "delay(10)" to your loop() method should take care of your issues. If there are still problems after that, it's either due to bad contacts or very long wires. In that case, you can try to add external pull-up resistors (about 1K to 10K); the built-in pull-up resistors are roughly 30K to 50K, so a switch might be susceptible to interference if several wires run in parallel over long distances.
  20. Switch the control reference to "Advanced" view and grab the IntegerBuffer or StringBuffer code snippet for the output you are interested in. That provides you with a function that will be called whenever that value changes (the updated value is passed in the newValue parameter). If you want to re-use the code, copy the LED class from LED.h, rename it and modify it to your needs.
  21. Adding queues would be a waste of memory, especially on a system that only has 2048 bytes of RAM. No matter how long you make the queue, you can't guarantee that it doesn't fill up, so you'd still be required to handle the case of not being able to transmit a message immediately. If you don't want to wait until the transmit buffer is free again, you can react differently when sendDcsBiosMessage() returns false. Instead of retrying to send the message until it succeeds, simply skip updating the variable that holds the last seen state, so the change is detected again the next time the program executes loop(). That's what the DCS-BIOS Arduino Library does.
  22. Short answer: yes for FC3 aircraft (but can be disabled by MP servers), don't know for other aircraft. Even if we only get graphical data out of the sim, a display with a video input is certainly the easiest, but by no means the only option. Long answer: I know there is an API to do that for FC3 aircraft, which can be disabled by unchecking "allow sensor export" in the MP server settings. I think it includes RWR data in addition to the radar contacts. No idea if the same API works for non-FC3 aircraft, although I suspect it doesn't. Even if the FC3 aircraft API does not work for other airframes, there might be a way to get the data by reading through the Lua files for the RWR, similar to what I did to piece together the content of the A-10C CDU. I wouldn't count on it, but I also don't want to say "this is impossible" without having spent several hours investigating. Assuming that all you can do is export the viewport, that still does not mean you must use a screen with a video input. Assuming you have some external monitor where you can put the exported image (e.g. a virtual screen or a second monitor that is otherwise used to watch TeamSpeak or something), you could write a program to grab the data from there and send it to a suitable microcontroller-driven display. An Arduino connected to a 250000 bps serial port could handle about two or three monochrome frames per second on a 320x240 display, which might be enough for the RWR; if you need more FPS, use something with an ARM processor and USB. How you drive the RWR display will depend on what type of display you get. It seems impossible to find one with the exact dimensions. I discussed this with Warhog recently and the options he is considering include using a slightly too small square display and enlarging the image with a fresnel lens, and using rear projection with one of those cheap pico projectors. If you want maximum realism (i.e. a working brightness knob in the right place), things get more complicated because even a square display of the correct size would likely interfere with the potentiometer for that knob (hence the rear projection idea); the original RWR uses a round CRT tube.
  23. This sounds like you connected external pull-down resistors to the A and B pins and connected +5V to the center pin on the switch. The DCS-BIOS Arduino Library assumes that the center pin on the switch is connected to ground and relies on the pull-up resistors that are integrated into the microcontroller to put the A and B pins into a defined state. Many "how to read a switch" tutorials have you use a pull-down resistor on the I/O pin and wire up the switch to connect 5V when it is closed. This will make the pin LOW when the switch is open and HIGH when the switch is closed. The other way to do it is to use a pull-up resistor on the I/O pin and wire up the switch to connect to ground when closed. This will make the pin HIGH when the switch is open and LOW when the switch is closed. The beginner tutorials use the first option because it makes the logic "look right" -- when the switch is closed / the button is pressed, you intuitively expect to read a logic "HIGH"/"1"/"on" value. Most real-world applications use the second option because the AVR chips have integrated pull-up resistors that can be enabled in software, so you don't have to use any external resistors.
  24. Try the following (warning: I didn't even try to compile this, I am on my laptop right now). #define DCSBIOS_IRQ_SERIAL #include "DcsBios.h" void setup() { DcsBios::setup(); pinMode(A0, INPUT); digitalWrite(A0, HIGH); // pullup } int value = 0; int newbtn = 0; int btn = 0; void loop() { DcsBios::loop(); value = analogRead(A0); if(value < 59 ) newbtn = 1; else if (value < 65) newbtn = 2; else if (value < 72) newbtn = 3; else if (value < 80) newbtn = 4; else newbtn = 0; if(newbtn != btn) { switch(newbtn) { case 1: while(!sendDcsBiosMessage("CMSP_ARW1", "1")); break; case 2: while(!sendDcsBiosMessage("CMSP_ARW2", "1")); break; case 3: while(!sendDcsBiosMessage("CMSP_ARW3", "1")); break; case 4: while(!sendDcsBiosMessage("CMSP_ARW4", "1")); break; case 0: default: switch(btn) { case 1: while(!sendDcsBiosMessage("CMSP_ARW1", "0")); break; case 2: while(!sendDcsBiosMessage("CMSP_ARW2", "0")); break; case 3: while(!sendDcsBiosMessage("CMSP_ARW3", "0")); break; case 4: while(!sendDcsBiosMessage("CMSP_ARW4", "0")); break; } } btn1 = newbtn; } } sendDcsBiosMessage() is being provided by the DCS-BIOS Arduino library now. It also returns a boolean success value and may fail to send the message, so you have to deal with that. The easy way to do so is to use it in the condition of an empty while loop so you retry until sending succeeds. This is not optimal (if it has to wait for the transmit buffer to free up, the CPU time is wasted instead of being used to update outputs), but should work in most cases.
  25. Using The GIMP, you can export a monochrome image in .xbm format. That's basically a text file containing a C array with the image data. That's what I used to make the font files for my altimeter demo. For the UTFT library, there is also an online conversion tool.
  • Create New...