PaulStoffregen
Well-known member
seems counter intuitive that I can send more packets succesfully when slower!
Just a blind guess, but maybe the faster speed is causing packet loss?
seems counter intuitive that I can send more packets succesfully when slower!
#include<FastLED.h>
#include <Artnet.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SPI.h>
#include <OctoWS2811.h>
#define NUM_LEDS_PER_STRIP 170
// Note: this can be 12 if you're using a teensy 3 and don't mind soldering the pads on the back
#define NUM_STRIPS 8
CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];
// Pin layouts on the teensy 3/3.1:
// WS2811_PORTD: 2,14,7,8,6,20,21,5
// WS2811_PORTC: 15,22,23,9,10,13,11,12,28,27,29,30 (these last 4 are pads on the bottom of the teensy)
// WS2811_PORTDC: 2,14,7,8,6,20,21,5,15,22,23,9,10,13,11,12 - 16 way parallel
//
// Pin layouts on the due
// WS2811_PORTA: 69,68,61,60,59,100,58,31 (note: pin 100 only available on the digix)
// WS2811_PORTB: 90,91,92,93,94,95,96,97 (note: only available on the digix)
// WS2811_PORTD: 25,26,27,28,14,15,29,11
//
// Artnet settings
Artnet artnet;
const int startUniverse = 0; // CHANGE FOR YOUR SETUP most software this is 1, some software send out artnet first universe as zero.
const int numberOfChannels = NUM_LEDS_PER_STRIP * NUM_STRIPS * 3; // Total number of channels you want to receive (1 led = 3 channels)
byte channelBuffer[numberOfChannels]; // Combined universes into a single array
// Check if we got all universes
const int maxUniverses = numberOfChannels / 512 + ((numberOfChannels % 512) ? 1 : 0);
bool universesReceived[maxUniverses];
bool sendFrame = 1;
// Change ip and mac address for your setup
byte ip[] = {192, 168, 0, 4};
byte mac[] = {0x04, 0xE9, 0xE5, 0x02, 0x69, 0xEC};
void setup() {
// LEDS.addLeds<WS2811_PORTA,NUM_STRIPS>(leds, NUM_LEDS_PER_STRIP);
// LEDS.addLeds<WS2811_PORTB,NUM_STRIPS>(leds, NUM_LEDS_PER_STRIP);
LEDS.addLeds<WS2811_PORTD,NUM_STRIPS>(leds, NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip);
//LEDS.addLeds<WS2811_PORTDC,NUM_STRIPS>(leds, NUM_LEDS_PER_STRIP);
LEDS.setBrightness(32);
artnet.begin(mac, ip);
// this will be called for each packet received
artnet.setArtDmxCallback(onDmxFrame);
}
void loop() {
artnet.read();
}
void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data)
{
sendFrame = 1;
//Serial.println(universe);
//Serial.println(byte(data[1]));
// Store which universe has got in
if (universe-startUniverse < maxUniverses)
universesReceived[universe-startUniverse] = 1;
for (int i = 0 ; i < maxUniverses ; i++)
{
if (universesReceived[i] == 0)
{
// Serial.println("Broke");
sendFrame = 1;
break;
}
}
// read universe and put into the right part of the display buffer
for (int i = 0 ; i < length ; i++)
{
// Serial.println("Insert");
int bufferIndex = i + ((universe - startUniverse) * length);
if (bufferIndex < numberOfChannels) // to verify
channelBuffer[bufferIndex] = byte(data[i]);
}
for(int i = 0; i < NUM_STRIPS; i++)
{
for(int j = 0; j < NUM_LEDS_PER_STRIP; j++) {
leds[(i*NUM_LEDS_PER_STRIP) + j].setRGB( channelBuffer[(i*NUM_LEDS_PER_STRIP) + j], channelBuffer[(i*NUM_LEDS_PER_STRIP) + j + 1], channelBuffer[(i*NUM_LEDS_PER_STRIP) + j + 2]);
}
}
LEDS.show();
LEDS.delay(10);
}
#define USE_OCTOWS2811
#include<OctoWS2811.h>
#include<FastLED.h>
#include <Artnet.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SPI.h>
#define NUM_LEDS_PER_STRIP 170
#define NUM_STRIPS 4
CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];
// Pin layouts on the teensy 3:
// OctoWS2811: 2,14,7,8,6,20,21,5
// Artnet settings
Artnet artnet;
const int startUniverse = 0; // CHANGE FOR YOUR SETUP most software this is 1, some software send out artnet first universe as zero.
const int numberOfChannels = NUM_LEDS_PER_STRIP * NUM_STRIPS * 3; // Total number of channels you want to receive (1 led = 3 channels)
byte channelBuffer[numberOfChannels]; // Combined universes into a single array
// Check if we got all universes
const int maxUniverses = numberOfChannels / 512 + ((numberOfChannels % 512) ? 1 : 0);
bool universesReceived[maxUniverses];
bool sendFrame = 1;
// Change ip and mac address for your setup
byte ip[] = {192, 168, 0,3};
byte mac[] = {0x04, 0xE9, 0xE9, 0x09, 0x69, 0xEC};
//------------------------------------------------------------------------------------------
void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data)
{
sendFrame = 1;
// Store which universe has got in
if (universe < maxUniverses)
universesReceived[universe] = 1;
for (int i = 0 ; i < maxUniverses ; i++)
{
if (universesReceived[i] == 0)
{
//Serial.println("Broke");
sendFrame = 0;
break;
}
}
// read universe and put into the right part of the display buffer
for (int i = 0 ; i < length ; i++)
{
int bufferIndex = i + ((universe - startUniverse) * length);
if (bufferIndex < numberOfChannels) // to verify
channelBuffer[bufferIndex] = byte(data[i]);
}
// send to leds
for (int i = 0; i < NUM_LEDS_PER_STRIP * NUM_STRIPS; i++)
{
leds[i].setRGB(channelBuffer[(i) * 3], channelBuffer[(i * 3) + 1], channelBuffer[(i * 3) + 2]);
}
if (sendFrame)
{
LEDS.show();
LEDS.delay(10);
// Reset universeReceived to 0
memset(universesReceived, 0, maxUniverses);
}
}
//------------------------------------------------------------------------------------------------------------
void setup()
{
LEDS.addLeds<OCTOWS2811>(leds, NUM_LEDS_PER_STRIP);
// LEDS.setBrightness(64);
artnet.begin(mac, ip);
Serial.begin(115200);
// this will be called for each packet received
artnet.setArtDmxCallback(onDmxFrame);
}
//------------------------------------------------------------------------------------------------------------
void loop()
{
artnet.read();
}
/*
This example will receive multiple universes via Artnet and control a strip of ws2811 leds via
Paul Stoffregen's excellent OctoWS2811 library: https://www.pjrc.com/teensy/td_libs_OctoWS2811.html
This example may be copied under the terms of the MIT license, see the LICENSE file for details
*/
#include <Artnet.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SPI.h>
#include <OctoWS2811.h>
// OctoWS2811 settings
const int ledsPerStrip = 22; // change for your setup
const byte numStrips = 8; // change for your setup
const int numLeds = ledsPerStrip * numStrips;
const int numberOfChannels = numLeds * 3; // Total number of channels you want to receive (1 led = 3 channels)
DMAMEM int displayMemory[ledsPerStrip * 6];
int drawingMemory[ledsPerStrip * 6];
const int config = WS2811_GRB | WS2811_800kHz;
OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);
// Artnet settings
Artnet artnet;
const int startUniverse = 40; // CHANGE FOR YOUR SETUP most software this is 1, some software send out artnet first universe as 0.
// Check if we got all universes
const int maxUniverses = numberOfChannels / 512 + ((numberOfChannels % 512) ? 1 : 0);
bool universesReceived[maxUniverses];
bool sendFrame = 1;
int previousDataLength = 0;
// Change ip and mac address for your setup
byte ip[] = {2, 0, 0, 200};
byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};
void setup() {
//Serial.begin(115200);
artnet.begin(mac, ip);
leds.begin();
initTest();
// this will be called for each packet received
artnet.setArtDmxCallback(onDmxFrame);
}
void loop() {
// we call the read function inside the loop
artnet.read();
}
void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data) {
sendFrame = 1;
// Store which universe has got in
if (universe >= startUniverse && universe < startUniverse + maxUniverses ) {
// read universe and put into the right part of the display buffer
for (int i = 0; i < length / 3; i++) {
int led = i + (universe - startUniverse) * (previousDataLength / 3);
if (led < numLeds)
leds.setPixel(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
}
previousDataLength = length;
if (sendFrame) {
leds.show();
}
}
}
#define USE_OCTOWS2811
#include<OctoWS2811.h>
#include<FastLED.h>
#include <Artnet.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SPI.h>
#define NUM_LEDS_PER_STRIP 170
#define NUM_STRIPS 2
CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];
// Pin layouts on the teensy 3:
// OctoWS2811: 2,14,7,8,6,20,21,5
// Artnet settings
Artnet artnet;
const int startUniverse = 0; // CHANGE FOR YOUR SETUP most software this is 1, some software send out artnet first universe as zero.
const int numberOfChannels = NUM_LEDS_PER_STRIP * NUM_STRIPS * 3; // Total number of channels you want to receive (1 led = 3 channels)
byte channelBuffer[numberOfChannels]; // Combined universes into a single array
// Check if we got all universes
const int maxUniverses = numberOfChannels / 512 + ((numberOfChannels % 512) ? 1 : 0);
bool universesReceived[maxUniverses];
bool sendFrame = 1;
// Change ip and mac address for your setup
byte ip[] = {192, 168, 1,231};
byte mac[] = {0x04, 0xE9, 0xE5, 0x02, 0x9D, 0x17};
//------------------------------------------------------------------------------------------
void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data)
{
sendFrame = 1;
// Store which universe has got in
if (universe < maxUniverses)
universesReceived[universe] = 1;
for (int i = 0 ; i < maxUniverses ; i++)
{
if (universesReceived[i] == 0)
{
//Serial.println("Broke");
sendFrame = 0;
break;
}
}
// read universe and put into the right part of the display buffer
for (int i = 0 ; i < length ; i++)
{
int bufferIndex = i + ((universe - startUniverse) * length);
if (bufferIndex < numberOfChannels) // to verify
channelBuffer[bufferIndex] = byte(data[i]);
}
// send to leds
for (int i = 0; i < NUM_LEDS_PER_STRIP * NUM_STRIPS; i++)
{
leds[i].setRGB(channelBuffer[(i) * 3], channelBuffer[(i * 3) + 1], channelBuffer[(i * 3) + 2]);
}
if (sendFrame)
{
LEDS.show();
LEDS.delay(10);
// Reset universeReceived to 0
memset(universesReceived, 0, maxUniverses);
}
}
//------------------------------------------------------------------------------------------------------------
void setup()
{
LEDS.addLeds<OCTOWS2811>(leds, NUM_LEDS_PER_STRIP);
// LEDS.setBrightness(64);
artnet.begin(mac, ip);
Serial.begin(115200);
// this will be called for each packet received
artnet.setArtDmxCallback(onDmxFrame);
}
//------------------------------------------------------------------------------------------------------------
void loop()
{
artnet.read();
}
chopperpix, I don't fully understand your description of what you are doing. I think it is the terminology you are using plus when you say "changed the patch to be 1 instead of 0" it's not clear to me if you mean channels or pixels. Let my try to help by stating a few basic things: Yes, I mean channels. I started at channel 1 instead of 0.
1 DMX (and ArtNet) universe has up to 512 channels (channels 0 - 511)
1 RGB Pixel uses 3 DMX channels. Not applicable here, but if you were using RGBW pixels they would likely use 4 DMX channels for each pixel.
Therefor, you can drive up to 177 pixels per universe with 2 channels left over (there's the number 2 that might be a clue). If you start with U0 Ch0, the last pixel will be on U0 Ch507, U0 Ch508, U0 Ch509. Channels 510 and 511 are leftover.
The 178th pixel could begin at U0 Ch510 and use channels U0 Ch510, U0 Ch511, U1 Ch0 and continue from there. You could also start the 178th pixel at U1 Ch0 and continue from there.
I suspect the issue is that you don't have your patch configured exactly right and that the "off-by-two" issue is related to the 2 extra channels in universe 0. Your sketch looks ok. Really? I thought it mattered not with OctoWS2811, just was memory inefficient.
You've not shown us your patch so I cannot be sure. Please tell or show us exactly how the patch is configure.
Update: From studying your sketch in more depth, I'm pretty sure the 178th pixel is using data from the channel buffer which corresponds to U0 Ch510, U0 Ch511, U1 Ch0. Note that your DMX controller doesn't necessarily have to send the full 512 channels of each universe (it's not guaranteed as part of the ArtNet spec.). My suggestion is, if your DMX controller patch allows it, start the 178th Pixel at U0 Ch510. Edit for clarity: Hopefully, your controller knows to use U0 Ch510, U0 Ch511, U1 Ch0, for the 178th Pixel. Again, if you only use lets say 30 pixels * 3 = 90 channels, you are saying that the LAST channel of U0 has to use up the last 3(or 4 depending on pixel) channels to properly map into U1?
Finally to all readers, this is rather complicated, so I might have gotten something wrong. Please correct me.
Interesting .. Why would the pixel I added to the beginning of U0 be completely useless -- it does not light up at all -- and yet still cause the rest of the strip to be in correct sequence? Also, U0 only had 156 pixels on it. That's 468 channels - quite a way from the 512 ceiling for U0.
// send to leds
for (int i = 0; i < NUM_LEDS_PER_STRIP * NUM_STRIPS; i++)
{
leds[i].setRGB(channelBuffer[(i) * 3], channelBuffer[(i * 3) + 1], channelBuffer[(i * 3) + 2]);
}
// send to leds
for (int i = 0; i < ledsPerStrip * numStrips; i++)
{
leds.setPixel(i, channelBuffer[(i) * 3 + channelOffset], channelBuffer[(i * 3) + 1 + channelOffset], channelBuffer[(i * 3) + 2 + channelOffset]);
}
void initTest()
{
for (int i = 0 ; i < ledsPerStrip * numStrips ; i++)
leds.setPixel(i, 127, 0, 0);
leds.show();
delay(500);
// send to leds
/*
* Added an offset for each universe (e.g. 2 Channels at the end of U0, than 4 Channels at the end of U1.... etc..)
*
* */
int i_universum = 0; // Index for the current universe
int tmp_channelOffset = 0; // the amount of the temporary channeloffset..
for (int i = 0; i < ledsPerStrip * numStrips; i++) {
if ((i % ledsPerStrip) == 0) {
if (i == 0) {
tmp_channelOffset = 0;
} else {
++i_universum;
tmp_channelOffset = channelOffset * i_universum;
}
}
leds.setPixel(i, channelBuffer[(i) * 3 + tmp_channelOffset], channelBuffer[(i * 3) + 1 + tmp_channelOffset],
channelBuffer[(i * 3) + 2 + tmp_channelOffset]);
}
TheDoctorB, you are quite right, and this was mentioned on page16 message #374 to #376 of this artnet thread. I hope that any further dev of the artnet lib should take this into account.
Ethernet.begin(mac, ip, dns, gateway, subnet);
Recalling this old (but great) thread because I'm working on an artnet project now.
seems everything works fine here with chamsys outputting multicast at 2.255.255.255 and teensy set at 2.0.0.x with 255.0.0.0 netmask.
The only difference in my code is the artnet.begin routine, I'm using artnet.begin() and initializing the ethernet communication before in the code, using the "full" init available in the Ethernet library:
Code:Ethernet.begin(mac, ip, dns, gateway, subnet);
I hope this is helpful for people who want to use teensy with the 2.x.x.x range.
Unfortunately artnet is a horrible protocol which uses broadcasts / multicast messages when not really needed. The unicast implementation is still not used much on stages...
So are you able to get more than 4 universes talking at a reasonable speed? My implementation seems to work up to about 3-ish before the LED outputs of the teensy start spazzing out...
Hi All,
Can anyone please give me a rather detailed description or perfectly working code to get 10 universes up and running quickly? I have a friend working on it now but we are only up to 6 working universes and if I can help him in anyway I'd like to as at the moment I pretty much just watch cause I know nothing about coding haha.
I am running a teensy 3.2 + octo adapter + w5200 Ethernet module running 1,600 LEDs and using Jinx to send data to the matrix.
I really just need 10 working universes asap if anyone out there has the files/code ready to go.
Cheers!
Andrew Gardner
I am that friend - Here is the link to a new thread on it. The code is for sACN e1.31.
https://forum.pjrc.com/threads/45760-E1-31-sACN-Ethernet-DMX-Performance-help-6-Universe-Limit-improvements?p=150625#post150625