My end goal:
I'm creating a DMX512-controlled light fixture which consists of 1 stepper motor and 4 powerful LEDs. I'm using Arduino Mega, DMX shield (with Conceptinetics library), PCA9685, TMC2130 (controlled using the combination of TMCStepper and AccelStepper) and some other stuff that is probably irrelevant.
What's happening in the code:
Each time a DMX frame is received, a callback to a function is produced. In this function, values of 5 sequential channels are extracted. If these values differ from the last remembered ones, then the goal brightness values and the stepper speed are recalculated. Note that the brightness values are remapped from 0-255 to 0-4095, since the PCA9685 has 12-bit registers.
Then, there's the main loop.
Main loop (previous iteration):
void loop() {
stepper.run(); // has to be called as often as possible so it won't miss steps
/* LED #1 */
if (led1CurrentValue != led1GoalValue) {
led1CurrentValue += (led1GoalValue > led1CurrentValue) ? 1 : -1;
pwmDriver.setPWM(PWM_LED1_PIN, 0, led1CurrentValue); // turned out to be a very slow blocking function
}
/* LED #2 */
// etc
}
pwmDriver.setPWM (from Adafruit_PWMServoDriver) turned out to be a very slow blocking function which resulted in the stepper being noticeably slowed down for the periods of time when a LED is moving towards its goal brightness value. To cope with that, it was decided to move the AccelStepper call to the timer interrupt at 10 kHz. Here comes the current iteration.
Main loop (current iteration):
void setup() {
Timer1.initialize(100);
Timer1.attachInterrupt(pollStepper);
}
void pollStepper() {
stepper.run();
}
void loop() {
/* LED #1 */
if (led1CurrentValue != led1GoalValue) {
led1CurrentValue += (led1GoalValue > led1CurrentValue) ? 1 : -1;
pwmDriver.setPWM(PWM_LED1_PIN, 0, led1CurrentValue);
}
/* LED #2 */
// etc
}
At first, it appeared that the problem was solved. Everything worked in harmony, the stepper moved stably no matter what was happening to the LEDs. But only at first.
The way the DMX library works is that you select your total number of channels, your start channel and then you read data from this fixed range. Something like that:
const int CHANNELS_TOTAL = 5;
DMX_Slave dmxSlave(CHANNELS_TOTAL);
dmxSlave.onReceiveComplete(onFrameReceiveComplete);
dmxSlave.enable();
dmxSlave.setStartAddress(1);
int channel1Value = dmxSlave.getChannelValue(1);
int channel2Value = dmxSlave.getChannelValue(2);
int channel3Value = dmxSlave.getChannelValue(3);
int channel4Value = dmxSlave.getChannelValue(4);
int channel5Value = dmxSlave.getChannelValue(5);
With that being said, the problem which I'm facing now, having moved to the interrupts, is that it only properly works if the starting address is in the low range. 1 or 2 basically. Farther than that everything begins to horribly stutter. 10, 17, 150, whatever - is a no go. It makes zero sense to me. Where's the logic in that?
This behavior is only observed when using interrupts, so I'm thinking the problem's tightly connected to them. Can someone enlighten me and help to come up with a solution?
Full code: pastebin (otherwise the post is too long)
UPDATE:
deeplowdock:
I allowed nested interrupts which solved it for me. I think this is an anti-pattern, but I'm just happy it works.
So the pollStepper function now looks like this:
void pollStepper() {
interrupts();
stepper.run();
}