Sign up Calendar Latest Topics
 
 
 


Reply
  Author   Comment  
e4mafia

Registered:
Posts: 24
Reply with quote  #1 
Hi guys, 

New to all of this but feeling ambitious. I've got some solid ideas of what I want to build, just need to figure the best way to implement. Looking at the DMX config files, it looks like Artemis' implementation seems to generally assume a 3 channel RGB output. If I'm hooking up (via Arduino) to a general RGB strip, this would work wonderfully and simply it seems. 
I'm definitely more interested though in doing things with the individually addressable lights, and being able to drive them from a single output data link from the Arduino. Strip of 10 lights gives me 10 individually controllable lights. But it doesn't seem that DMX understands this? or at least the way that Artemis implements it.

If I look at the shields on entry

 

<event type="PLAYER_SHIELDS_ON" continuous="yes">

<!-- steady blue light -->
<timeblock mseconds="1000">
<setvalue index="0" value="0" change="0"/>
<!-- red value of first light box -->
<setvalue index="1" value="0" change="0"/>
<!-- green value of first light box -->
<setvalue index="2" value="200" change="0"/>
<!-- blue value of first light box -->
</timeblock>
</event>

I'm wondering what is actually happening over the serial link here. My interpretation (don't have anything plugged in yet) is that the serial RX on my Arduino will receive 3 'channels' via the DMXlibrary. I'll get a value on each channel representing the color. But there's not enough here to tell my 2812 what to do on an individual light basis. What do the various fields in this DMX event represent? Specifically <timeblock seconds="xyzzy"> and the "change" field in the set value commands? Is this defining a rate of change over a period of time?

I'm thinking at this point, that its going to be easier for me to just rewrite the DMX config items to represent a more general transmission to the arduino - instead of reading the values that DMX wants to send, have it instead some kind of discrete indicator, that the Arduino will then read and trigger a function and do all the color and activation work on that side instead. 

i.e. instead of sending the values for lighting in 'realtime' over the channel, have it just send a simple value, which then triggers the raiseShields() function I make on arduino

Couple of possibilities here
- I'm reinventing the wheel because I don't understand what DMX is actually trying to do
- I want to do something that DMX can't really do for me in this implementation and I've figured out a kludgy way to pull it off
- I'm way off base and barking mad
- This will never work so I should stop before I jump off a cliff of disappointment. 

I haven't seen any documentation for Artemis that explains what the signaling it doing, so I'm definitely guess here. Any ideas?

e4mafia

Registered:
Posts: 24
Reply with quote  #2 
I'll definitely share what I discover after my RedBoard comes in (combines an Uno with an FTDI chip, so best of both worlds) I'll probably set up a serial write and try to capture what signaling comes across and try to reverse engineer that to decipher Thom's implementation in Artemis.

Actually now that I'm thinking of it - is the formatting and usage of the DMX config file a general standard? That code block I posted in the previous one?I'll dig around and share what I find.

But if anybody already knows, feel free to share 😉
e4mafia

Registered:
Posts: 24
Reply with quote  #3 
Haven't been able to play with the receive side yet, but having some fun with my test strip, creating cool effects.
My thinking now is that I'll set the Arduino to read the inbound signaling packets, and look at things as an on/off per channel, with each channel representing a different action. Kind of translating the Artemis event into a discrete channel signal on/off to the Arduino, which will then use that signal to begin, or stop a given function. It seems like this will give me much more of what I want than just live feeding the channel values over and translate them there. In that case, I'm stuck having to program the effects in the Artemis config file, but I'm just not really seeing how to do more elaborate things that way. Maybe I'm just missing the forest for the trees?

Shields Up --> Steady value of (channel/value) = 0/1. -->Arduino runs a loop of the shieldsUp() function which will do a wipe up  of blue lights. 
Shields Down --> Steady value of 0/0 -->Arduino now stops running the shuieldsUP() function.
Red alert On --> 1/1
Red alert Off -->1/0


Uh oh, I think I may have cornered myself already. Can you multithread on an Arduino?
Back to the drawing board....
Angel of Rust

Registered:
Posts: 149
Reply with quote  #4 
It sounds like you've been working out the details of your light control scheme.

As you noted earlier, there is a choice to make between how much programming you want to do with the script vs. how much programming you want to do with the Arduino. Since the Arduino approach offers more flexibility, especially with respect to logic, it's been my preference to do the programming there.

In regards to your last remark, I would like to point out that you do not need multi-threading to accomplish the task you are describing. Here is an outline of how it works in my programs for reference:
  • The sketch has a number of global variables to keep track of the active animation states and their progress. One common structure I use is to have a 1-dimensional integer array, with one "row" for each one of the possible animations. The row stores a "-1" if the animation is inactive and stores a positive number to represent the "frame" of each animation.
  • The main loop calls a number of functions, including a function ("update_animation()") to advance to the animation frame, and a function ("update_lights()") to update the LED hardware. These two functions are separate because the update_lights() function typically needs to be trigger more often.
  • If the update dmx function on the Arduino detects a change from Artemis, it can be programmed to enter a "-1" or a frame number into the array to start (or stop) the animation.
  • Calls to update_lights() or update_animation() are triggered from an "if" statement that checks a timer. If the right number of milliseconds (or microseconds, according to taste) have gone by, the corresponding function is called and the timer reset.
  • update_animation() increments the frame count for active animations and then adjusts the corresponding LED states (intensity, color, etc.) in a separate array according to the animation scheme
  • update_lights() updates the actual hardware states (either via the PWM pins or normal digital pins, according to taste) based on the data in the lights array. This scheme is only needed if there is any hardware overlap between lights (such as an LED matrix).
The timer-based coding method above allows the Arduino controllers to do many different things at the same time.
e4mafia

Registered:
Posts: 24
Reply with quote  #5 
So I abandoned trying to reinvent the wheel in serial and decided to leverage my expertise in networking. All that time spent working at Brocade and Broadcom is worth more than a paycheck 😉

I'll walk through my programming process and share the code.

It was far simpler to utilize the ArtNet capabilities of DMX Tools than to go the route of figuring out the serial registers inside my Uno / Redboard

So with that in mind, we need to have an ethernet port on the arduino, so I bought one of these: https://www.amazon.com/gp/product/B00HG82V1A/ref=oh_aui_detailpage_o08_s00?ie=UTF8&psc=1

Ethernet port acquired, I needed to look at the general schema of what I'm trying to do. I'm more interested in controlling all logic from the arduino, since thats easy enough to code, and that way I don't have to spend forever in DMX tools tweaking everything to get what I'm after, or creating tons of channels for the individually addressable LED strips. I'm looking for a lot more than just all the lights do one thing at a time. The layout is going to be
  • 2 strips, one on either side of the main screen, for the captain to have a quick visual on the shields and energy status. The right strip will show energy like a gauge, with the color shifting from yellow to orange and red in addition to turning off 1 light at a time from top to bottom. The left side will be shields, as a gauge extending up for front shields and down for rear. They will retreat toward the center of the strip as the strength weakens.
  • 2 Strips, either overhead or on the sides of the play area, to give a sense of motion. Yellow chase lights for impulse, with increasing speed of the chase effect to match impulse rate. Turns purple and does same for warp. Working the idea of having a different animation for impulse, but for now its just a different color.
  • 1 strip overhead, in the front of play area for a red alert effect. swelling brightness in and out, with an initial strobe-ish effect when alert first comes on
  • 1 strip centered above play area for environmental effects - soft green for in nebula, yellow pushing when docked, etc. Will also handle flashing and other damage indicators.

As you can see, its a lot going on. Easy enough to do in C++, but I'm completely lost as to how I'd pull it off in DMX only. So how do I translate the DMX output into something more useful like "turn this on, this off" instructions? Easy enough. A channel for each strip, and either a binary 0-1 result for on or off, or a menu of options like 1-4 for the warp speeds. OK. So into DMX tools I go and create a multi-channel ARTnet device. I leave the single channel of brightness in as 0-255 for flexibility, but remove the RGB channels as they aren't really needed. 

Pasted Graphic.jpg 

Theres the device config.

Next we look at a simple beginning of the DMX output

Pasted Graphic 1.jpg 


Each of the impulse levels will output a single number.

So the bones are there, now its time to go over to the arduino and see what gets sent.

I have the serial monitor set to print the data in each channel left to right, starting at channel 0. Which thanks to some WireShark investigations, I learned resides in byte 18 of the buffer. Right now it will print bytes 18-30. Why up to 30? Why not. I may end up using more channels, and I'd like to be able to see them quickly for debugging purposes.


Screen Shot 2018-09-29 at 7.54.10 PM.png 



So what we are looking at here is the output of the first DMX packet sent by Artemis (DMX Editor test, to be specific). It will send an update about every 4 seconds, if there are no changes to the data. If there is a change, it will immediately send another packet. I'll turn on red alert and shields, and you can see the changes


Screen Shot 2018-09-29 at 7.58.57 PM.png 


Ignore the shields state output. I need to update that. The byte print out above Is accurate. Engines are in byte 19 and shields in 20. The bottom print is off. 
Lastly, the individual effects in the arduino are HEAVILY based on the multitasking concepts explained here:https://learn.adafruit.com/multi-tasking-the-arduino-part-3/overview 
Many segments of the code are straight up lifted from there, and then modified a bit.
So if you think any of this is cool and worth using, here's some snippets of the code for setting up the ethernet instance and a packet buffer for incoming data


#include <Ethernet.h>
#include <EthernetUdp.h>
#include <Adafruit_NeoPixel.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 
//manual MAC address of the ethernet port on the Arduino. 
// this can be completely arbitrary as this will be directly connected to the 
//arduino from the control PC on a private network
IPAddress ip(192, 168, 100, 100); 
unsigned int localPort = 6454;      // local port to listen on
// buffer to hold incoming packet, DMX packet is pretty much always 530 bytes
byte packetBuffer[600]; 
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;



And now the setup for bringing  up the serial and ethernet connections


void setup()
{

Ethernet.init(10); // Most Arduino shields

//start ethernet session
Ethernet.init(10);
Ethernet.begin(mac, ip);

// start udp session
Udp.begin(localPort);

// wait for serial connection to come up
Serial.begin(250000);
while (!Serial){
;
}

}


void loop() // the main event here
{

// check if there is data in the queue
int packetSize = Udp.parsePacket();              //set the buffer to the size of the incoming packet
if (packetSize) {                                          // conditional only if a packet exists
Udp.read(packetBuffer, packetSize);             //heres where the action really starts. This reads the packet into the buffer
Serial.println("Packet Received");                 // self explanatory for debugging

//main actions to take upon finding a packet. First one is different, as Im using a single channel for all engine activity. A result of 1-5 is impulse, 6-9 is warp
if (packetBuffer[19] < 6)
{
engines1.Color1 = engines1.Color(200,150,0);  //sets the engines object to yellow for impulse
engines1.State = packetBuffer[19];                 // set the object state to match whats in byte 19 of the DMX payload
}
else
{
engines1.Color1 = engines1.Color(200,0,150); // if its not impulse its warp, so purple
engines1.State = (packetBuffer[19]-4);           // this adjusts the state back to a 1-5 range for determining speed. Like I said, one effect for both options
}

shields.State = packetBuffer[18];                   // updates shield state
redalert.State = packetBuffer[20];                // updates shield state
environment.State = packetBuffer[21];         // updates environment state

for (int i = 18; i < 30; i++){                       // walks through bytes 18 to 30 and prints them to serial
Serial.print(packetBuffer[i], HEX);
Serial.print(" ");
}                                                               //prints various statuses
Serial.println();
Serial.print("Engines State = ");
Serial.println(engines1.State);
Serial.print("Red Alert State = ");
Serial.println(redalert.State);
Serial.print("Shields State = ");
Serial.println(shields.State);
Serial.print("Environment State = ");
Serial.println(environment.State);

engines1.Update();                                   // update functions to call the next step in each effects animation
shields.Update();
environment.Update();
redalert.Update();
}
}



I've omitted the code for the light object class, which includes the functions for each animation, and update function, and a timer function to check if enough time has passed to go to next animation step when update is called. If it isn't time, the update ignores the effect. All of that is heavily derived from the NeoPixel article referenced above. 

Next problem is how the heck to do I get the crappy 5v signal out to the lights if they are upwards of 15 feet away? Well cat5 cable seemed the obvious choice to me, since I could use it to carry signal, AND power for the LED strip. Only problem is the degradation of the control signal from the arduino at that distance. In steps the SN75174 and SN75176 transceivers. They will transform that single 5v signal into a differential pair of signals (good thing I have twisted pairs of wires handy 😉 ) . So 4 of the light control signals go out on the 4 channels of the SN75174. The remaining signal will be split to two lines and travel from an SN75176 in transmit mode. Each of the LED strips will then be connected to a control receiver box, from which it will get power, and the data signal, which is turned back into a single 5v single by the SN75176 on the board.


Pasted Graphic 2.jpg 


I haven't built the main control board which will send out all the signals yet, just 4 of the 6 receivers. All of this will be powered by an ATX power supply in an old computer case I pulled out of the basement. The control board, and power distribution will live inside that case as well.
BTW, the idea for the transceivers is from Teknynja, and is described here: https://www.teknynja.com/2014/02/driving-ws2812neopixels-rgb-leds-over.html

When everything is all said and done, I'll post a parts list, schematic, and put the finished code on GitHub for everyone to use. I want to thank everyone in this community for inspiring me (especially Angel of Rust) to take on this project. I've never used an Arduino before. My background is a network engineer, but for a time I was an avionics and weapons tech in the army, working on Apache helicopters, so much of my knowledge there came into play here, but most of this has all been learned on the fly. I've really enjoyed this so far, despite some of the heavy bugs I've come across in the hardware and code as I've gone. 

I'm gonna call it a night both here, and in the workshop (aka the seriously messy corner in my office where I keep the soldering iron)

Good night all!

-Bob


e4mafia

Registered:
Posts: 24
Reply with quote  #6 
Hey Angel of Rust or anyone else that knows anything about PCB design.... any advice on design? I tried creating an account over on Fritzing to ask someone to sanity check what I've done, but their sign up process is messed up. (Captcha not working). So I went full bore and DL'ed a copy of Eagle. Took a while to get the hang of it, but I like it. I see that you made a few PCBs for your control panels, wondering if you wouldn't mind weighing in with an opinion on mine? SV2 will be connected to an RJ-45 cable, which is carrying the signal for the SN75176 on pins 4 and 5, and +5v and - on the other pairs. 1, 3, 7 are - and 2, 6, 8 are +5v. Each + and - are on a twisted pair together. SV1 goes out to the light strip. I couldnt figure out how to move the pins on the schematic, so its a little bit messy, but it translated nicely on the PCB.

Screen Shot 2018-09-30 at 5.01.39 PM.png
Here's the schematic for the receivers, for anyone interested. 
And now a graphic of the PCB design:

Screen Shot 2018-09-30 at 5.03.09 PM.png    

I'll try to find other sources for help with the design before I order it. It'll will sure beat wiring up the boards manually - too many easy mistakes to make.







Angel of Rust

Registered:
Posts: 149
Reply with quote  #7 
Quote:
Originally Posted by e4mafia
Hey Angel of Rust or anyone else that knows anything about PCB design.... any advice on design?

Screen Shot 2018-09-30 at 5.03.09 PM.png    




I think the overall design looks good. If I understand your previous post correctly, you have built a breadboard prototype and verified that the design is working. That is good. I couldn't tell if each of the receivers needed to be individually addressed, or if each one has its own control signal from the main controller. If you could speak to that point, it would help to understand. The arrangement of the PCB looks like each board gets its own signal.

As for the physical layout of the PCB itself, I have a few thoughts:
  • the entire board can be made smaller by moving the components closer together. It will save you some money and the soldering won't be much more difficult
  • I recommend you put some screw holes in the board so it's easy to mount to other enclosures. Just make sure the clearances around the screw heads are large enough for the other components
  • SV2 appears to be designed to mount the RJ45 jack on a separate breakout board that has the 8 pins arranged in a line. If you haven't already bought the breakout boards, you could consider mounting the jacks on the PCB directly using the two staggered rows of pins that are typical for RJ45 jacks. No matter how you choose to mount the jack, you will likely want to make sure it is located entirely over the board so it is less likely to move when plugging and unplugging the cat5 cable.
  • a lot of PCB designs have the GND conductor as a fill covering the entire face of the board that is not being used for other traces. I am told this is a good practice. Also it is easy to do in EAGLE and looks really good. The only caveat is to make sure you specify the minimum amount of isolation between traces
  • the VCC trace seams a little too close to the other pads on SV1 and SV2. Since you have a lot of room to work with, I recommend increasing the separation between them. It will make accidental shorts less likely during assembly.
  • since the PCB is quite small, the current limits for the traces are not likely to be an issue. However, it is easy to check and making the traces wider is easy to do in EAGLE. Since you are driving LEDs off of this board, I recommend you check them. Here is a calculator: https://www.4pcb.com/trace-width-calculator.html

That's all I can think of. Good luck!

e4mafia

Registered:
Posts: 24
Reply with quote  #8 
All great advice, thanks!
  • I did already have the breakouts for the RJ-45. I didn't even think to do a staggered series of holes in Eagle, my brain was locked on the fact that I couldn't do that on my breadboard. If I do another run, I'll do that. Could have saved 5 bucks on breakouts 😉 - I guess v 0.2 will not need breakouts for the jacks. 
  • tightened it up and got rid of a lot of extra space.
  • forgot about mounting holes. Thats a really good idea. I have a friend who's gonna 3d print some small enclosures for me, so its not quite so important. Gonna try to use a slot to mount in place.
  • I tried to figure out the ground plane in Eagle, but gave up after a bit. Maybe worth another look.
  • Total voltage moving through the non power lines will be 5 volts, and very low current. The lines to SV1 will pull up to a theoretical 3.6 amps, but in practice will be much less. The only lighting effect that uses all the LEDs at once is red alert, and some other environmental effects, but they wont ever be on at full bright, and not for long at that. Maybe a few flashes of white for damage effects, but sustained higher current shouldn't be a problem. I could also just run dedicated, thicker traces to those lines right?
Gonna go take another pass at this one, and also the control board, which I just realized would be a hell of a lot simpler to build as a shield on the arduino, rather than screwing around with connectors and such. Just found the Eagle template for one, Yay!

e4mafia

Registered:
Posts: 24
Reply with quote  #9 
First round boards are back. Like a dope I mislabeled +5 and gnd, so when I first hooked ip up, not much happened except a shitload of heat generating on the jst whip. Figured it out and swapped, and it works like a champ now. I wish I had put more space between the holes for the resistor, and used a natural footprint for the rj45 rather than mounting it onto a breakout and then the breakout to the board - but everything else is pretty hunky dory. To say I've learned a lot from this is an understatement. And now in fine myth busters fashion, I'm feeling the "if its worth doing, its worth overdoing" bug, and wanting to build out nice neat boards for everything to really clean this thing up. But of course that's more money.

Out of curiosity, would anyone be interested in buying one of these setups from me? I can probably manufacture them without too much stress at this point, and could recoup some of the cost in R&D. Any takers ? 😉
e4mafia

Registered:
Posts: 24
Reply with quote  #10 
Down to 17 hours until the big event. My test run on Wednesday went as smooth as can be. The great giggle to me here is that 6 of the systems in use for this will be Macs, for a windows native game 😉

I didn't get all of the lighting effects to do everything I wanted. I guess thats what a 2.0 code rev is for. But for the 1.0 version of hardware I am very happy. The Arduino's network connection is really flaky, and I sometimes have to reconnect power a dozen times before it comes up, once it does, we're cooking with hot fire! he receiver boards work perfectly. The transmit board is 100% as well. I didn't do a PCB for that yet, since I've only got the need for 1 of them, but my OCD overdo-er is telling me at some point I'll PCB that one too. The distribution PCBs also work well, but I think there's a minor physical flaw in the location of things in terms of wire routing in the case. Something to think about for V2.

Heres a block diagram of how its all worked together, along with some photos for your enjoyment.
I'll post the finished code after the weekend and push it to Git for everyone to have to do with what they please.


Screen Shot 2018-11-02 at 5.53.08 PM.png

Block Diagram of Signals. Power is also sent to receivers via the distribution boards.

IMG_1638.jpg 
Components in the case....some creative rigging to get it all to stay in place. The vertical pins for power on the bistro boards, I'll probably remove and just solder direct tot he boards, but leave the other end as a disconnect-able line. 


Screen Shot 2018-11-02 at 5.30.09 PM.png 
Receiver PCB design
Screen Shot 2018-11-02 at 5.30.14 PM.png
  Distribution board design
  Screen Shot 2018-11-02 at 5.30.01 PM.png
  
Eventual PCB for the transmit board.





e4mafia

Registered:
Posts: 24
Reply with quote  #11 
Learned a lot, the event was a success. Not without problems of course. Nearly melted some wires at the very beginning not noticing a short on my lighting controller. Might only be 5v, but that ATX power supply has a lot of Amps to push over those tiny wires!

Wifi there sucked, so we ended up needing to switch to wired, but had to "order out" for a switch and a bunch of cables. Should have planned ahead for that. 
Here was the bridge layout: Screen Shot 2018-11-06 at 9.06.31 PM.png
Rationale for the setup was Comms behind the captain, so they were close for constant interaction, and science next to weapons for the info sharing there. Engineering where it was with a big monitor so the captain can see at a glance what's up over there.

My DMX setup  for the energy meter needs a little  work, as the output is a little wonky. The code on the Arduino for outputting the effect to the WS2812B is solid though, so there's half the work done already. I want to add 'static' like effects to the shield meters when a hit is taken, but haven't quite figured that one out yet.

Where to go from here? The Arduino Mega I'm using has a LOT of outputs, so maybe strobe lights, smoke machines, a klaxon....who knows? Anyone have any cool ideas?

Angel of Rust

Registered:
Posts: 149
Reply with quote  #12 
Look cool! Thanks for sharing all the details. Do you have some photos of the setup in action?
e4mafia

Registered:
Posts: 24
Reply with quote  #13 
I absolutely CANNOT believe this, but I didn't take a single picture. Epic FAIL. I guess I'm just going to have to run it again 😉

Now I need to justify to myself buying a full compliment of laptops or all in ones to have a fully useable on-demand bridge for events.

plus 27 inch touchscreens.....and a smoke machine, and strobe lights, and HUGE ass subwoofers. Rotating beacon lights, shaker motors for the seats.....

and then..... 


Previous Topic | Next Topic
Print
Reply

Quick Navigation:

Easily create a Forum Website with Website Toolbox.