Thanks a lot for the feedback!
- Every 4 pixels should be the same – I'm using 144 LED/m strip for the sake of output power, and grouping them together in bunches of 4 to save DMX channels.
- The strobe trigger triac is connected to pin 13 through a high pass filter that makes it trigger on a rising edge. It's intended to work as follows:
DMX 0-7: off
DMX 8-14: single flash
DMX 15-255: flash rate slow to fast
I tried installing 4.0.0A, but it doesn't seem to work – haven't checked very closely, but the test code from my earlier post seems to only return zeroes. It does not seem to freeze, though.
I made some changes to the code above, but nothing seems to have changed. Here are the current versions:
Strobe only, no pixels:
Code:
#include <cstring>
#include <TeensyDMX.h>
namespace teensydmx = ::qindesign::teensydmx;
teensydmx::Receiver dmxRx{Serial1};
// Buffer in which to store packet data
uint8_t packetBuf[122]{0};
constexpr int kChannel = 122; // strobe channel
constexpr unsigned long kDMXTimeout = 1000; // 1s
constexpr uint8_t kLEDPin = LED_BUILTIN;
// Constants for flashing rate
constexpr int32_t kPeriodMax = 500;
constexpr int32_t kPeriodMin = 50;
uint8_t buf[1]; // Buffer used for reading the DMX data.
uint8_t lastValue; // The last value received on kChannel.
elapsedMillis lastFrameTimer; // Keeps track of when the last frame was received.
// Flashing state
int32_t period = kPeriodMax;
int64_t phi = 0;
void setup() {
pinMode(2, OUTPUT);
digitalWriteFast(2, LOW);
pinMode(kLEDPin, OUTPUT);
digitalWriteFast(kLEDPin, LOW);
// Start the receiver
dmxRx.begin();
lastFrameTimer = kDMXTimeout;
}
void loop() {
// return of -1 means no data
int read = dmxRx.readPacket(packetBuf, 1, 122);
int64_t t = millis();
if (read == 122) {
lastValue = packetBuf[121];
lastFrameTimer = 0;
}
if (lastFrameTimer <= kDMXTimeout) {
if (lastValue > 0 && lastValue < 8) {
digitalWriteFast(kLEDPin, LOW);
} else if (lastValue > 8 && lastValue < 15) {
digitalWriteFast(kLEDPin, HIGH);
} else if (lastValue > 15) {
// Use a wave equation to make the speed-ups and slow-downs smoother
int32_t newPeriod = map(lastValue, 15, 255, kPeriodMax, kPeriodMin);
if (newPeriod != period) {
phi = (t*(period - newPeriod) + newPeriod*phi)/period;
period = newPeriod;
}
int32_t v = (t - phi)%period;
if (v < period/2) {
digitalWriteFast(kLEDPin, HIGH);
} else {
digitalWriteFast(kLEDPin, LOW);
}
} else {
digitalWriteFast(kLEDPin, LOW);
}
}
}
Pixels only, no strobe:
Code:
#include <cstring>
#include <TeensyDMX.h>
#include <Adafruit_NeoPixel.h>
#define PIX_PIN 17
#define PIX_COUNT 120
#define PIX_BRIGHT 40
namespace teensydmx = ::qindesign::teensydmx;
teensydmx::Receiver dmxRx{Serial1};
Adafruit_NeoPixel strip(PIX_COUNT, PIX_PIN, NEO_GRBW + NEO_KHZ800);
// Buffer in which to store packet data
uint8_t packetBuf[122]{0};
// The last values received
uint8_t rgb[122]{0};
void setup() {
pinMode(2, OUTPUT);
digitalWriteFast(2, LOW);
strip.begin();
strip.show();
strip.setBrightness(PIX_BRIGHT);
// Start the receiver
dmxRx.begin();
}
void loop() {
// return of -1 means no data
int read = dmxRx.readPacket(packetBuf, 1, 122);
// check if enough data for all LEDs was received
if (read >= 120) {
if (memcmp(packetBuf, rgb, 120) != 0) {
memcpy(rgb, packetBuf, 120);
// group LEDs in 4's
for(int i = 0; i < 199; i=i+4){
for(int p = 0; p < 4; p++){
strip.setPixelColor(i+p, rgb[i], rgb[i+1], rgb[i+2], rgb[i+3]);
}
}
}
strip.show(); // refresh strip only if enough data was received
}
}
Full version:
Code:
#include <cstring>
#include <TeensyDMX.h>
#include <Adafruit_NeoPixel.h>
#define PIX_PIN 17
#define PIX_COUNT 120
#define PIX_BRIGHT 40
namespace teensydmx = ::qindesign::teensydmx;
teensydmx::Receiver dmxRx{Serial1};
Adafruit_NeoPixel strip(PIX_COUNT, PIX_PIN, NEO_GRBW + NEO_KHZ800);
// Buffer in which to store packet data
uint8_t packetBuf[122]{0};
// The last values received
uint8_t rgb[122]{0};
constexpr int kChannel = 122; // strobe channel
constexpr unsigned long kDMXTimeout = 1000; // 1s
constexpr uint8_t kLEDPin = LED_BUILTIN;
// Constants for flashing rate
constexpr int32_t kPeriodMax = 500;
constexpr int32_t kPeriodMin = 50;
uint8_t buf[1]; // Buffer used for reading the DMX data.
uint8_t lastValue; // The last value received on kChannel.
elapsedMillis lastFrameTimer; // Keeps track of when the last frame was received.
// Flashing state
int32_t period = kPeriodMax;
int64_t phi = 0;
void setup() {
Serial.begin(9600);
pinMode(2, OUTPUT);
digitalWriteFast(2, LOW);
strip.begin();
strip.show();
strip.setBrightness(PIX_BRIGHT);
pinMode(kLEDPin, OUTPUT);
digitalWriteFast(kLEDPin, LOW);
// Start the receiver
dmxRx.begin();
lastFrameTimer = kDMXTimeout;
}
void loop() {
// return of -1 means no data
int read = dmxRx.readPacket(packetBuf, 1, 122);
// check if enough data for all LEDs was received
if (read >= 120) {
if (memcmp(packetBuf, rgb, 120) != 0) {
memcpy(rgb, packetBuf, 120);
// group LEDs in 4's
for(int i = 0; i < 199; i=i+4){
for(int p = 0; p < 4; p++){
strip.setPixelColor(i+p, rgb[i], rgb[i+1], rgb[i+2], rgb[i+3]);
}
}
}
strip.show(); // refresh strip only if enough data was received
}
int64_t t = millis();
if (read == 122) {
lastValue = packetBuf[121];
lastFrameTimer = 0;
}
if (lastFrameTimer <= kDMXTimeout) {
if (lastValue > 0 && lastValue < 8) {
digitalWriteFast(kLEDPin, LOW);
} else if (lastValue > 8 && lastValue < 15) {
digitalWriteFast(kLEDPin, HIGH);
} else if (lastValue > 15) {
// Use a wave equation to make the speed-ups and slow-downs smoother
int32_t newPeriod = map(lastValue, 15, 255, kPeriodMax, kPeriodMin);
if (newPeriod != period) {
phi = (t*(period - newPeriod) + newPeriod*phi)/period;
period = newPeriod;
}
int32_t v = (t - phi)%period;
if (v < period/2) {
digitalWriteFast(kLEDPin, HIGH);
} else {
digitalWriteFast(kLEDPin, LOW);
}
} else {
digitalWriteFast(kLEDPin, LOW);
}
}
}