I’m (still) working on a small project controlling DMX-lights (using Art-Net). At the moment I’m working on the “Movement-generator” and what I basically do is to use sine and cosine to calculate the DMX values (0-255) for the pan- and tilt-channel, like with this method:
public void runSineMovement() {
double degrees = x;
double radians = Math.toRadians(degrees);
double sine = Math.sin(radians);
double dmxValue = (int) ((sine * 127) + 127);
dmxValuesOBJ.setDmxValuesInArray(1, (int) dmxValue);
SendArtnet.SendArtnetNow();
x = x + 1;
if (x > 360) {
x = 1;
}
}
x = 1
I then have a ScheduledExecutorService that will call that method on a regular interval, like this:
int speed = 100;
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleAtFixedRate(SineMovement::runSineMovement, 0, 100000 * speed, TimeUnit.NANOSECONDS);
Above is working just fine, moving head (tilt-channel in this example) is moving perfectly. Now I want to use the “fine-channel”, that is, go from 8bit to 16bit (from 1 channel to 2 channels controlling the tilt-channel) so I can get smooth movement even at very slow speed. Remember, "fine-channel" have to go from 0 to 255 first and then "coarse-channel" can go to 1, then "fine-channel" from 0 to 255 and then "coarse-channel" to 2, and so on.
Earlier I build a movement-generator with “triangle-effect” where I looped from 0 to 65.536 and back to 0 and so on, and on every run I calculated the “coarse-channel” (counter/256) and the “fine-channel” (counter % 256) and that approach is working just fine.
Any ideas on how to approach this when using sine and cosine when generating the effect? Can I use the approach from the triangle-generator calculating “coarse” and “fine” using division and modulus?
EDIT: When thinking about it, I don't think the "fine" should have the form as a sine-wave, I mean, the "fine" will (if using sine) go very, very, fast, both up and down, and that will mess things up if the "coarse" is still going "up". I guess the correct is that the "fine" will always have the sawtooth-shape -> sawtooth from zero to max when coarse is going up, and sawtooth from max to zero when coarse is going down. Does that makes sense?
Thanks
You should calculate the sine-wave just for the values 0 - 65535 and then use the splitting method you used for the triangle waveform to part it to the two channels like this:
In this code I used several improvements:
I replaced your increment +
iffor the x value with an increment and a modulus calculation.I used improved typing:
doubleconstants wherever possible (32767.0instead of32767) so the program doesn't cast theintto adoublein each run.int dmxValueinstead of casting tointmultiple times.Instead of division and modulus for your coarse and fine values I used the faster bit shift right (
>>) and binary and (&) operators.The fine value consists of the 8 least significant bits of your number, so you can simply "mask out" all the others with a binary and operation.
The coarse value consist of the "other" 8 bits (most significant bits of a 16-bit value, that you are effectively using), so you can bring them 8 bits ot the right (equals a division by 2 to the power of 8), and then - just to make sure, again mask out all other bits.
Don't mix up the logical AND (
&&) with the binary AND&used here, the former one can only be used withbooleanvalues.Why will this work: the fine value will not oscillate between 0 and 255 (in a sine form!) for each change of the coarse value, because the code calculates just one sine wave and "splits" the values into fine and coarse. So if you have e.g. a value of 255 for
dmxValue, this will give youfineDmxValueas 255 andcoarseDmxValueas 0. But for a value of 256 fordmxValue, thefineDmxValuewill be 0 while thecoarseDmxValuewill be 1.The calculation of fine and coarse is independent of the way you generate your waveform in
dmxValue.