moritzruth / node-enttec-open-dmx-usb

💡 A Node.js library for interacting with the Enttec Open DMX USB Interface
MIT License
13 stars 5 forks source link

Not working #82

Open ScreamZ opened 1 year ago

ScreamZ commented 1 year ago

Hello,

I'm trying this library with the following code and nothing happens really, I get a small white flash, like in the following video

Here is my code (I'm on OSX with an M1 mac) I use an 8 channel mode light see the doc CLNB600_Cameo_DMX_Control_Table_EN.pdf

import { EnttecOpenDMXUSBDevice as DMXDevice } from "enttec-open-dmx-usb";

enum C {
  MechPan = 1,
  MechTilt = 2,
  Dimmer = 3,
  Strobe = 4,
  Red = 5,
  Green = 6,
  Blue = 7,
  White = 8,
}

(async () => {
  const device = new DMXDevice(await DMXDevice.getFirstAvailableDevice());

  device.setChannels({ [C.MechPan]: 255, [C.Dimmer]: 255, [C.White]: 255 }, true);
})();

https://user-images.githubusercontent.com/6640835/212354944-88b346d5-73a3-4cbc-8a46-26841f00337b.MOV

moritzruth commented 1 year ago

As answered at https://github.com/node-dmx/dmx/issues/148, I think I can’t help you. Your code seems to be right, so it’s probably got something to do with the timing of BRK.

You could maybe try changing the 0 in this line to something else (1, 200, ...) but I can’t guarantee this will do: https://github.com/moritzruth/node-enttec-open-dmx-usb/blob/e1a78c604466b4f96357a190df894fd548048626/src/index.ts#L134

ScreamZ commented 1 year ago

I can confirm this is related to the break.

0 is to slow, i put an higher value around 88, but as we need 88 microsecond maybe the good way is to use this blocking code for the break according to the spec

const child_process = require("child_process");

child_process.execSync("usleep 88");

Or this lib https://www.npmjs.com/package/sleep

which is what is defined in the spec http://www.dmx512-online.com/dmx512_packet.html

Can you try this value on your setup? Or I'll just make a pull request to have this configurable. Also I'll try micro sleep next week and keep you in touch

moritzruth commented 1 year ago

I don’t want to make sleep a dependency because it does not seem to provide pre-built binaries (i.e. it’s a pain to use it on Windows).

I think the best option would be to add a constructor option for passing a usleep-compatible function and propose using https://www.npmjs.com/package/sleep in the README.md.

It would be great if you could try whether it works with usleep(88).

ScreamZ commented 1 year ago

@moritzruth It's in my plan, i'll do the integration of the device in the next week, be sure I'll update this thread with intelligence when i have new

iovaris commented 1 year ago

I was experiencing the same issue after moving my code to an M1 Mac. I can also confirm that changing line 134 to 88 fixed the issue.

moritzruth commented 1 year ago

I just published v4.0.1 (I forgot to build before publishing v4.0.0). Please take a look at the new section in the README.md and let me know if this works for you. I also changed the two delays in sendUniverse from 0 to 1. As the DMX spec doesn’t have requirements for the maximum time of BRK and MAB, this should already suffice for compliant devices (so no need for usleep).

@ScreamZ @iovaris

ScreamZ commented 1 year ago

@moritzruth Thanks, what timing! I'm expected to write the DMX part of the code in the next 30 days, I'll for sure give feedback.

We have two sparkling machines and one light

ScreamZ commented 1 year ago

Hi @moritzruth,

Here is my first test pass.

  1. I had to switch to sleep library, because the node-sleep doesn't provide stuff for M1 mac ?

Test without external lib

Doesn't works. Just as before.

But as setTimeout relies on various things such as CPU capabilities, I can understand that this is tricky.

Test with library

92 µs seems to be too short.

After some test, I'm able to make it works with two code :

The first is based on a Rust implementation algorithm from a library and pause for 51ms (doesn't rely on setTimeout) :

  const device = new DMXDevice(
    await DMXDevice.getFirstAvailableDevice(),
    true,
    (ignoreValueForTest) => {
       sleep.msleep(51);
    }
  );

Note that you can replace (as described in the sleep library) with Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 51);

I've been able to reduce this frame up to 20ms, below it starts glitching, as read from https://docs.openlighting.org/ola/doc/latest/dmx_cpp_client_tutorial.html

Waiting for the tests on real device (raspberry PI, on linux)

ScreamZ commented 5 months ago

So far after some experiencing i can confirm that on a good CPU https://github.com/davidmarkclements/atomic-sleep works for pausing. It relies on atomics API. which sleep without CPU overhead.

Also note that this is not a microsleep, its a ms sleep, but it looks like that it works, probably due to some internal implementation mechanism of node serial.

ScreamZ commented 5 months ago

Also take a look at this awesome project https://github.com/benkuper/Chataigne