Tinkerkit DMX Shield and IMP

Hi all,

I would first like to congratulate the IMP team for their awesome product. This thing makes internet communication very easy.

I am trying to emulate the kaylee project (Imp+DMX) with the tinkerkit DMX shield for the arduino:
http://www.tinkerkit.com/dmx-master-shield/
(schematic): https://www.dropbox.com/s/trshtgif8bshnkd/dmx_shield_Rev4.pdf

I have changed the solder pads on the dmx shield to accept uart configuration (basically switch all 4 jump resistors to the other pads - http://www.deskontrol.net/blog/using-tinkerkit-dmx-shield-with-deskontrol-dmx-library/).

So once I changed the pads, I set the imp pin 1(tx) to the tx pin on the shield (pin 2), and imp pin 2 (rx) to rx pin on shield(pin1). At this point I do not get any DMX signal (I know because the power supply I am using will set all lights to 100% when no DMX, then drop them all to programmed levels if DMX comes through). I have tested the shield with the arduino and it works fine, so I know the shield is ok.

Here is the imp code (basically the kaylee code):

`//////////////////////////////////////
// Kaylee controlling lighting devices via DMX-512

// configure Serial UART
// dmx512 uses 8 data bits, 1 start bit, 2 stop bits, no parity bits, no flow control
//hardware.uart12.configure(250000, 8, PARITY_NONE, 2, NO_CTSRTS);

// pin 5 is a GPIO used to select between receive and transmit modes on the RS-485 translator
// externally pulled down (100k)
// set high to transmit
hardware.pin5.configure(DIGITAL_OUT);
hardware.pin5.write(1);

// build up a static 512-device DMX frame
local outBlob = blob(1024);

// populate the blob with null data
for (local i = 0; i < 512; i++) {
outBlob.writen(0x00, ‘b’);
}

function setLevel(addr, level) {
// send DMX512 command to set device at "addr"
outBlob.seek(addr);
outBlob.writen(level, ‘b’);

// enable transmitter
hardware.pin5.write(1);

// manually send out the break and mark-after-break
hardware.pin1.configure(DIGITAL_OUT);
// break
hardware.pin1.write(0);
imp.sleep(0.0001);
/*
hardware.pin1.write(1);
imp.sleep(0.00001);
*/

hardware.uart12.configure(250000, 8, PARITY_NONE, 2, NO_CTSRTS);
hardware.uart12.write(outBlob);

}

function refreshLevels() {
// manually send out the break and mark-after-break
hardware.pin1.configure(DIGITAL_OUT);
// break
hardware.pin1.write(0);
imp.sleep(0.0001);

hardware.uart12.configure(250000, 8, PARITY_NONE, 2, NO_CTSRTS);
hardware.uart12.write(outBlob);

}

function set(value) {
    try {
        local command = split(value, ",");
        red = command[0].tointeger();
        green = command[1].tointeger();
        blue = command[2].tointeger();
        server.log(format("red: 0x%02x green: 0x%02x blue: 0x%02x", red, green, blue));
    } catch (err) {
        server.error("Invalid Input");
    }
    setLevel(1, 0); //set these to 0 to test dmx without having to have input in planner
    setLevel(2, 0);
    setLevel(3, 0);
}

imp.configure(“Kaylee DMX512 Controller”,[],[]); //removed inputport

setLevel(1,0x00);
setLevel(2,0x00);
setLevel(3,0xff);

function refresh() {
//server.log(“Refreshing DMX devices”);
refreshLevels();
imp.wakeup(0.2, refresh);
}

refresh();

/////////////////////////////`

I have jumped the solder pads for DE and RE enable back to the original configuration on the DMX shield because I am not worried about receiving DMX signal right now. In fact I am not using the imp pin 5 at all since the solder pads define that it is receiving (RE-EN to GND, and DE-EN to Vcc). The shield and imp are both powered by a 5V regulated power supply, I have even tied the grounds together, but it still doesn’t work.

I guess I am wondering if the kaylee code should work, and if I am missing something. I appreciate any help anyone can give me. This should have been a simple project, however this is proving to not me.

Thanks

So, if the TX and RX modes are both enabled, you should receive what you send out. Do you see that?

The shield is outputting 5v to the imp, which is out of spec: you should be using a zener clamp (search for that on the forum) or level translator for the imp’s 3.3v pins. The TX side is, however, fine because the SN75176BD has a Vih(min) of 2v (ie, it will accept anything over 2v as logic 1).

Not sure why outblob is 1024 bytes as it should only be 512 (only 512 bytes are initialized).

Thanks Hugo,

I appreciate your timely response. I fixed the enabled modes so only the Tx is on. I narrowed down the issue a bit. First, my pin1 was nonoperational, due to my sparkfun breakout not having enough pressure on the pin (scrolled over that issue on the forums yesterday). I got out my scope and found that the imp’s uart tx was making it across the 485 translator, and back again to the uart for the receiving end. The problem is the actual data packets that are being created by the imp, more specifically the break and mark after break.

Attached are scope pics of two different DMX transmissions. The yellow waveform is from the Imp, and the blue is from an arduino sending a working DMX transmission. They are both 16 packets of DMX information long so I could get the two to look similar on the scope. Again the blue waveform works fine. As you can see, the Imp’s break period is too long (~>800uS). USITT DMX512-A standards indicate the break period should be from 96 to 176 uS. The arduino transmission fits within the break period the Imp is giving! I read the Imp+DMX post and noticed Peter mentioned that there is a glitch in the hardware not allowing it to transition quick enough. I am curious because the Kaylee board works?? Is there something special they had to do for this transition time?

One idea I have is using a separate pin to pull the uart tx line to ground for the break, and MAB, instead of reconfiguring the uart line every time manually. Do you think would work? Or will this damage the internal circuitry of the Imp?

Thanks for your time.

Kaylee works fine with the DMX devices we have here, but all ones are different. YMMV!

Yes, the reconfiguation of the UART appears to be the problem here; until there’s a native DMX API on the imp then you’re likely to be out of luck I’m afraid.

hows about googling around the ardunio forums and see how they do it? in the following example, they switch the baud down temporarily to 125 to create the break

http://playground.arduino.cc/Learning/DMXSerial

The imp doesn’t do baudrates that low :frowning:

We might be able to come up with something intermediate. We’ll have a think…

Sorry, I should clarify, its 125000 bps they drop too and transmit a 0 to create the break.

That could well work, depending on the timing requirements for re-configuring the serial port and starting to send the packet.

Note that you can make squirrel calls faster by reducing the number of table lookups. eg:

port <- hardware.uart12; // do this once at the start of your code

port.configure(xxx)

is quicker than

hardware.uart12.configure(xxx)

I wonder if a another thing you could do “in the break” is do a read, the idea being you could see if any other masters were on the line (and therefore you were clashing with them as you can have only one)

If it sensed there were, it could stop sending and say capture the data for learning purposes for example.

anyway, thats running before we’re walking, get the imp to send valid dmx first!

The reconfiguring of the serial only from 250000 to 125000kBs is still too long. It was shorter but there is still a limitation there. One thing I did was configure the serial to 125000 at the beginning, send the break and MAB, then configure for 250000, send blob, then reconfigure back to 125000 right after blob send so that the reconfigure is done AFTER the message was sent. This made a beautiful 90uS break and MAB. However, when the serial is reconfigured back to 250000, the line drops low for 10uS, then high for about 150uS. Only after that wait can I sent the blob.

I guess I need to wait for an API. I assume there is some internal software code that is running even in between the low and high commands. This would be taken care of with an API I assume. The Arduino does not have this higher code running under the main program, so there is no real limitation with the reconfiguring of the ports.

Now…I did try using another pin set as a digital output to pull the uart line low and then back high. This did make a decent looking DMX signal with an appropriate break, and MAB timing with the blob being sent right after when it needs. However the line was only pulled to ~2.8V low since the uart line was high (voltage equilibrium?). I am curious to use a PNP to pull line directly to ground. The digital output low should tie to ground, however I might be doing something wrong. I am by no means an electrical engineer. This is probably damaging the imp!!!

Hugo, the table lookup did save time (~25uS). But still not enough. Thanks for that tid-bit of information. Also If you need some help testing an API or anything I am in the lighting industry working extensively with DMX-512A devices and controls and would be more than happy to test an API.

I appreciate everybody’s time and input with this.

If you want to use another pin to make a low level, you should use an external AND gate. Hook one input to the UART and one to a GPIO output on the imp (the “enable” pin). The output of the AND gate will be the DMX signal.

“enable” pin high -> data from UART goes through AND gate unchanged.
“enable” pin low -> AND gate output is low, no matter what UART does

Tying them together directly will not get you down to 0v, because both are driven pins - one is trying its best to drive high, the other is trying its best to drive low. If you’re seeing 2.8v, the one driving high is winning :slight_smile:

Have you checked out Peter’s DMXSimple library he created for Arduino? I’ve used this successfully on many different types of DMX controllers. I know it won’t solve your issues but might help see how it’s done with an Arduino:

https://code.google.com/p/tinkerit/wiki/DmxSimple
(View library code)

It works!

The And Gate was exactly what I needed, thanks Hugo. No more reconfiguring the uart or digital pins. Set once at beginning, then just use another digital out pin to manually drive the break and MAB. I appreciate everybody’s time and help with this. I will upload schematics and code in the future. Now on to the software side of the forums to get HTTP and agents set up for Android/IOS app!!!

Thanks again!

Great news, I can’t wait to see what you do software-side

Folks this discussion has been a great help in setting up my DMX interface with the imp and using the Kaylee code. As I am not a programmer I am having some difficulty with syntax in sending a command to either the channel input or the full frame input. would someone be willing to give me an example?
https://api.electricimp.com/v1/abcxxxccxcexxxf0/200xxa5xxxc7xxxe1 "what do i type here?) I know it is channel and level but I cant quite get it Thanks CAB

Do you have access to agents? Are you using an AND-gate?

If you have agent access (if not @beardedinventor should sign you up if you ask):

Agent Code:
`// HTTP DMX controller --> Agent Code
// https://agent.electricimp.com/yourimpidhere/?ch1=0&ch2=0&ch3=0&ch4=0&ch5=0&ch6=0&ch7=0&ch8=0&ch9=0&ch10=0&ch11=0&ch12=0 --> example http request
// Can recieve full 12 channel string (?ch1=0&ch2=0&ch3=0&ch4=0&ch5=0&ch6=0&ch7=0&ch8=0&ch9=0&ch10=0&ch11=0&ch12=0)
// or just channels needed (?ch1=125&ch5=0&ch8=125&ch12=0)

dmxsize <- 12;
outBlob <- blob(dmxsize);

http.onrequest(function(req, res) {
server.log(“Request Recieved”);
foreach(i,v in req.query) {
outBlob.seek(i.slice(2).tointeger());
outBlob.writen(v.tointeger(), ‘b’);
}
device.send(“newDMX”, outBlob);
server.log(“DMX Sent”);
res.send(200, “DMX Has been Sent”);
})`

And Imp code:

`// HTTP DMX Controller
// Writes DMX based on HTTP request

dmxoutput <- hardware.uart57;
andgate <- hardware.pin2;
dmxoutput.configure(250000, 8, PARITY_NONE, 2, NO_CTSRTS);
andgate.configure(DIGITAL_OUT);
dmxsize <- 12; // Number of DMX Channels
outBlob <- blob(dmxsize);
refreshrate <- 0.01; // Seconds

for (local i = 0; i < dmxsize; i++) {outBlob.writen(0x00, ‘b’)}; // populate the blob with null data

function DMXrefresh() {
andgate.write(0);
andgate.write(1);
dmxoutput.write(outBlob);
}

function idle() {
DMXrefresh();
imp.wakeup(refreshrate, idle);
}

agent.on(“newDMX”, function(value) {
outBlob = value;
DMXrefresh();
})

imp.configure(“DMX”,[],[]);
idle();`

The agent code will receive a request query and translate the query parameters into channel numbers for the DMX blob. Just send:
https://agent.electricimp.com/yourimpidhere/?ch1=255&ch2=125, this will change ch1 in the DMX stream to 255 and ch2 to 125. You can send just channels you want to change (?ch4=125&ch12=0) or any single channel as well.

I have methods for http post and json as well…

Thank you so much I will look into getting agent access. and thanks for the syntax. CAB

@physicsnole Have you found the software-only solution is giving the exact timing you need?

How are people dealing with the time access of DMX changes, for example “fade channel 30 to 20% over 30 seconds”?

I know this is not part of the DMX protocol itself but am wondering if people are implementing this axis, client-side, server-side or a clever hybrid of the two?