Wearable LED panels, unique project

Status
Not open for further replies.

dwain

Member
Hi,

I'm currently working on a small hobby project for a festival for 3 days i'm making a wearable led suit for me and 2 friends (so 3 suits total). One day I saw somewhere a picture of a suit what would look great for use and I made a own technical photo for it:
dude1.jpg

WhatsApp Image 2017-11-17 at 13.19.58.jpg

So we needed 10 led panels and we have a total leds amount of 1007. We are using WS2813 led strips 60meter a led which I ordered from China and hopefully wil get next week.

I already start working on a ledpanel (with some 5m WS2812b led strip I had here) and made a 37x8 led panel and succesfully ran some demo's tests and Glediator on it. My main idea of the suit is to make some simpel paterns in Gledatior put it on a sd card and load it in to the Teensy. Also the accu part is covered.

The only main thing is that it are 10 own panels and I'm looking for the best way to soldern, connect and program them.

It would be great if it is 1 big panel but if you see the top and left shoulder have a skew in it and each led strip there is different length so connecting them from top with data is not the best way?

It also would be great if I can show some scrolling text on the panels 3,8,2,1 and 4 where the scrolling text starts on panel 3&8 (combined).

What are your tips, suggestions?
 
Given it's a wearable and you really want the number of connections to be minimal you may want to use a intervening pixel array between your pattern generation and OctoWS. So the idea would be that you wire the OCTO strips in ways that make sense mechanically and keeps the 8 strips roughly the same length, then produce a map of how those numbered pixels line up with one or more squares and create X and Y lookup arrays. So your patterns go onto the virtual squares, even the dead space, and then run through your lookup arrays writing the pixels that actually exist into the OctoWS array. You can do this ahead of time in programing system of choice, or do it on the fly, which will be slower but more flexible (and using more memory).

You can also have an array that stores the X/Y and possibly Z value of each pixel and use that procedurally to generate effects, for example starbursting out from the chest where brightness = distance from 0,0,0 point via Pythagoras. Have used this method when I had circular a backlight using a mixture of free pixels and rings that made no sense whatsever in an X/Y space that was getting Perlin noise. Getting the maths done for 1000+ pixels would be pushing the Teensy CPU on anything clever though, and not a good solution for things like text unless you feel like solving inside/outside maths for a font.
 
Given it's a wearable and you really want the number of connections to be minimal you may want to use a intervening pixel array between your pattern generation and OctoWS. So the idea would be that you wire the OCTO strips in ways that make sense mechanically and keeps the 8 strips roughly the same length, then produce a map of how those numbered pixels line up with one or more squares and create X and Y lookup arrays. So your patterns go onto the virtual squares, even the dead space, and then run through your lookup arrays writing the pixels that actually exist into the OctoWS array. You can do this ahead of time in programing system of choice, or do it on the fly, which will be slower but more flexible (and using more memory).

You can also have an array that stores the X/Y and possibly Z value of each pixel and use that procedurally to generate effects, for example starbursting out from the chest where brightness = distance from 0,0,0 point via Pythagoras. Have used this method when I had circular a backlight using a mixture of free pixels and rings that made no sense whatsever in an X/Y space that was getting Perlin noise. Getting the maths done for 1000+ pixels would be pushing the Teensy CPU on anything clever though, and not a good solution for things like text unless you feel like solving inside/outside maths for a font.

I'm using a teensy 3.6, but i'm new to Teensy. I used Arduino some years ago and 2 years ago I made a ledsuit with 150 leds with FastLED and a Arduino. Can you give me some more information about the intervening pixel array and mapping in the arrays? thanks!
 
Also I want to place the Glediator files on the SD card and combine the code with FastLED. Is that possible?
 
Several ways to do it, but one choice is to define an array the total width and height of chest +arms (27*25 in your drawing) with each array having a Uint32_t so 2.7kb of Ram (uint32_t screenMemArray [27][25];). Your pattern generation process writes to that as a flat surface including the pixels that do not exist above the shoulders etc but means you don't have to worry about bounding errors or such like things.

You then transfer the pixels that exist into your most likely highly convoluted strand arrangement. You could use a set of sequential if statments breaking each segment out to octoWSpixel number (starts with 0 as first pixel of strip 8, runs to pixel n of first strip, first pixel of strip 2 is n+1 etc.

uint32_t tempcolour =0;
if (currentPixel>27&&<54) tempcolour = screenMemArray[currentPixel%27+54][currentPixel/2] //<-insert whatever logic works here - will be some combo of modulo and divide with offsets
if (currentPixel>27&&<54) tempcolour = screenMemArray[currentPixel%27+27][currentPixel/2]
// etc for each strip
leds.setPixel(currentPixel, tempcolour );

You also have an lookup array of bytes, one for each real pixel. Either a multiaxis one byte strandArray [lengthOfLongestStrand*8][2] where the last location 0 is the X byte and the location 1 is the y byte or

byte xLookupValues [8*lengthOfLongestStrand]
byte yLookupValues [8*lengthOfLongestStrand]

and run them seperatly. This array is populated either by hand or by writing some offline code and to generate them and doing any hand tweaking required. then you can run through the array setting pixels
for (int currentPixel=-;currentPixel<8*striplength;currentPixel++){
uint32_t tempcolour =0;
tempcolour = screenMemArray[xLookupValues[currentPixel],[yLookupValues[currentPixel]];
leds.setPixel(currentPixel, tempcolour );
}
Would suggest mocking this up in a desktop enviroment first, processing https://processing.org/ would be a good choice since with care you can port working code straight across. Or you can have your processing code generate SD data files that match your strip structure and just have the setPixel return churn through them.

Edit Re reading glediator files, fastLED can use OCTOWS as a LED driver so if you have a working method already that will still work just swapping out the display code. If you don't then you need to dig into the file structure yourself, and budget time accordingly.

edit edit https://github.com/FastLED/FastLED/wiki/Parallel-Output
 
Also I want to place the Glediator files on the SD card and combine the code with FastLED. Is that possible?

Here's a thread where someone reported success doing basically this same thing (well, except the "combine the code with FastLED" part). The code is in mesg #16.

https://forum.pjrc.com/threads/46229&viewfull=1#post153927

The file only has raw LED data, not any info about required timing. The code just plays it as fast as possible. Without a delay and using only a fairly small number of LEDs (only 1000), it's likely to play much too quickly. Adding a delay is pretty easy. :)
 
Yes the part with getting SD card data instead of COM data from USB is gonna work I think (at the moment I dont have a micro sd card here haha).

Only also for example led panel 2 the chest I will connect data IN at top left then and of first strip go again up on second strip etc. etc. but it is:
4 equal long strips, then 2 with 2 leds less, then 2 with 4 less leds and then again 2 strips with 2 less and then 4 equal long strips. How can I get a pattern on it but keep all 'leds next to each other'.
 
test1.jpg

I'm now first making these panels (2, 5, 6 and 7) I will make panel each panel as a own panel and want also to connect is as own panel to a digital output of the Teensy. I will make all panel from top left snake till end.

But what is the best way to make a patern on it with gladiator (dont mind if its sd card or usb because its almost same code).

Panel 2 is 14xmax26 leds
Panel 5 and 7 are 5x14 leds
Panel 6 is 5x17 leds

So the best is to use it as 1 big led panel with the maximal L and H? So 15W and 43H (leds) and how to make code to use first 14x26 leds to panel 2, etc...?
 
I now solderned the body panel (panel 2) and I'm creating some code to get the Glediator data onto the panel. Because the panel misses some leds in top on 4,5,6,7,8 and 9 row I wanted to use this https://macetech.github.io/FastLED-XY-Map-Generator/

I also want to use FastLED. I now have this code:
Code:
#include <FastLED.h>
#define NUM_LEDS 299
#define DATA_PIN 6
#define CMD_NEW_DATA 1
#define BAUD_RATE 500000

CRGB leds[NUM_LEDS];

void setup() {
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  Serial.begin(BAUD_RATE);
}
int serialGlediator () {
  while (!Serial.available()) {}
  return Serial.read();
}
void loop() {
  while (serialGlediator () != CMD_NEW_DATA) {}
  
  Serial.readBytes((char*)leds, NUM_LEDS*3);
  
  FastLED.show();
}

But how to implement this code?
Code:
// Params for width and height
const uint8_t kMatrixWidth = 14;
const uint8_t kMatrixHeight = 26;

#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
CRGB leds[ NUM_LEDS ];
#define LAST_VISIBLE_LED 355
uint16_t XY (uint16_t x, uint16_t y) {
  // any out of bounds address maps to the first hidden pixel
  if ( (x >= kMatrixWidth) || (y >= kMatrixHeight) ) {
    return (LAST_VISIBLE_LED + 1);
  }

  const uint16_t XYTable[] = {
     0,  51,  52, 103, 356, 357, 358, 361, 362, 363, 252, 303, 304, 355,
     1,  50,  53, 102, 104, 153, 359, 360, 202, 251, 253, 302, 305, 354,
     2,  49,  54, 101, 105, 152, 154, 201, 203, 250, 254, 301, 306, 353,
     3,  48,  55, 100, 106, 151, 155, 200, 204, 249, 255, 300, 307, 352,
     4,  47,  56,  99, 107, 150, 156, 199, 205, 248, 256, 299, 308, 351,
     5,  46,  57,  98, 108, 149, 157, 198, 206, 247, 257, 298, 309, 350,
     6,  45,  58,  97, 109, 148, 158, 197, 207, 246, 258, 297, 310, 349,
     7,  44,  59,  96, 110, 147, 159, 196, 208, 245, 259, 296, 311, 348,
     8,  43,  60,  95, 111, 146, 160, 195, 209, 244, 260, 295, 312, 347,
     9,  42,  61,  94, 112, 145, 161, 194, 210, 243, 261, 294, 313, 346,
    10,  41,  62,  93, 113, 144, 162, 193, 211, 242, 262, 293, 314, 345,
    11,  40,  63,  92, 114, 143, 163, 192, 212, 241, 263, 292, 315, 344,
    12,  39,  64,  91, 115, 142, 164, 191, 213, 240, 264, 291, 316, 343,
    13,  38,  65,  90, 116, 141, 165, 190, 214, 239, 265, 290, 317, 342,
    14,  37,  66,  89, 117, 140, 166, 189, 215, 238, 266, 289, 318, 341,
    15,  36,  67,  88, 118, 139, 167, 188, 216, 237, 267, 288, 319, 340,
    16,  35,  68,  87, 119, 138, 168, 187, 217, 236, 268, 287, 320, 339,
    17,  34,  69,  86, 120, 137, 169, 186, 218, 235, 269, 286, 321, 338,
    18,  33,  70,  85, 121, 136, 170, 185, 219, 234, 270, 285, 322, 337,
    19,  32,  71,  84, 122, 135, 171, 184, 220, 233, 271, 284, 323, 336,
    20,  31,  72,  83, 123, 134, 172, 183, 221, 232, 272, 283, 324, 335,
    21,  30,  73,  82, 124, 133, 173, 182, 222, 231, 273, 282, 325, 334,
    22,  29,  74,  81, 125, 132, 174, 181, 223, 230, 274, 281, 326, 333,
    23,  28,  75,  80, 126, 131, 175, 180, 224, 229, 275, 280, 327, 332,
    24,  27,  76,  79, 127, 130, 176, 179, 225, 228, 276, 279, 328, 331,
    25,  26,  77,  78, 128, 129, 177, 178, 226, 227, 277, 278, 329, 330
  };

  uint16_t i = (y * kMatrixWidth) + x;
  uint16_t j = XYTable[i];
  return j;
}

http://puu.sh/yz6QF/7133052208.png
 
What the page is doing is producing a procedure that returns which LED on a strand a given x/y position is by auto generating a look up table as suggested above. Chop off the top section to go with your other defines, the chunk from
uint16_t XY (uint16_t x, uint16_t y) {
down is the procedure itself. You will need to create multiples, on for each panel, say XYArm, XYTorso etc

So you need to iterate through your SD card or other data and call the XY routine, with your co-ordinate values and then write your colour to the returned pixel on the strand

look at the fastled xymatrix example and specifically the line
leds[ XY(x, y)] = CHSV( pixelHue, 255, 255);

suggest at first running the example unmodified, and confirm it lights all pixels (albiet skewed around due holes in matrix) then drop in the code you got above in place of the existing XY function. That should just work with no further changes and you can then work to change the names to add more panels, and just ladd more leds calls to duplicate the test pattern across multiple panels

leds[ leftArmXY(x, y)] = CHSV( pixelHue, 255, 255);
leds[ rightArmXY(x, y)] = CHSV( pixelHue, 255, 255);
leds[ torsoXY(x, y)] = CHSV( pixelHue, 255, 255);

Edit: Do note that this defines memory for the total matrix size including missing pixels, so watch your total program space and total in use RAM as you get LED strip memory, lookup table memory and your buffer for glediator memory
editedit: that example code you have above has a massive problem that it assumes a single panel. You will need to work out how the serial stream discriminates between different panels and probably write or find a more robust parser to get reliable results.
 
Last edited:
Yes I'm thinking of creating 1 big led panel inside gledatior witch covers all panels (so a panel of 28 width and 57 height) and then make each panel on a own Digitalpin on the Teensy. And then only the big part to map the pixels from the serial data. So led 0-73 top left arm etc.

Only no idea or example how to completly make this
 
Last edited:
You can do that, but means you may end up with dead space taking up memory and/or time.

This is where some playing in processing may be helpful to look at how basic logic works in drawing grids and converting data between them

What you will be doing is replacing
Serial.readBytes((char*)leds, NUM_LEDS*3);

with some form of process that reads a byte from the serial buffer, increments a counter and then works out what the x and y value for that counter is
for example where your x dimension is arrayWidth
int xvalue = counter%arrayWidth; //uses the modulo command
int yvalue = counter/arrayWidth; //divides in integer math, which removes remainder
Then you need to work out which part of the array to call either by lookup or a pile of if statements

if (xvalue<8 && yvalue<21) drawtoleftArm(xvalue,yalue);
if (xvalue>=8 &&xvalue<20&& yvalue<21) drawtotorso(xvalue-8,yvalue);
if (xvalue>=8 &&xvalue<20&& yvalue<21) drawtotorso(xvalue-8,yvalue);
if (xvalue<9&& yvalue>=21) drawToLeftLeg(xvalue,yvalue-21);

Then each drawto... function takes the X and Y value provided and feeds it into the relevant array lookup discussed above to draw to a pin output and a pixel.

If this is all seeming complex that's because it is. You said in your title this is a unique project and is going to require a lot of custom work by you to pull off. Breaking it down into small chunks that can work will help rather than trying to work out how to do things all in one go, and building prototypes to confirm things are working the way you think they are will also help.

Things to watch for/research
Arrays start from zero, not 1
If arrays do weird things, you have probably failed to bounds check
Don't assume a serial data stream will not miss/gain bits out in the field, even if early versions on the bench work, add some form of sync recovery process.
Power for all these will be complex, make sure you have enough batteries, and wire sizes are large enough
Wearables are probably the most aggressive environment for electronics after space, plan test and think worst cases for all connectors and joins.
Assume you will have to pull things apart to fix, don't design anything that you will never be able to get apart
When you design something impossible to take apart anyway, bring spares of that part
Reasonable probability at least one of these will short out and melt things, especially if plan is to dance in them - make sure you can shut down/shed the suit quickly, finding a tiny on/off switch while wire in your pants is red hot can be tricky.
 
So you still say make 1 big led panel inside glediator, make some animations, export that to sd card. Load that data in and match it to a x and y position. Then match that animations to the coresponding led panels and write the leds to a function for each panel. Inside that function do the mapping for the not equal ledstrips inside that panel?

Regarding the advice for the wearable, we have ws2813 with 2x data and we have made a + and - on end and start of each led strip. Also on top and bottom they are wired to each other and each 2 led strips are again connected with +/- to make really sure if something breaks it still get power for the rest of some parts of the strips. Also each panel has a own +/- from the base.
 
I now made some code only to test and play with the chest.

This is the panel:
chest1.jpg

It are 14 in width and 26 (max) in height.

I made in Glediator a matrix of 14 x 26 and output as vs_tl (vertical snake, top left start)

I first tested with this code:
Code:
void loop() {
  while (serialGlediator () != CMD_NEW_DATA) {}

  
  Serial.readBytes((char*)leds, NUM_LEDS*3);
  FastLED.show();

This works and it directly controls all leds (only equal height so the panels with less leds in the top are moved on to the next panel)

Then I wanted to make it in a for loop so I can control more things and made this code:
Code:
void loop() {
  byte r,g,b;
  int i;
  while (serialGlediator () != CMD_NEW_DATA) {}

for (i=0; i < NUM_LEDS; i++) {
    Serial.readBytes( (char*)(&leds[i]), 3);
  }   
  FastLED.show();
}

This did the same thing but now I have a for loop to map some leds with. In glediator I made a gif with a image with each row a own color this is original gif:
Untitled-1.gif And this is the output you see that on the fifth row it goes wrong because its 1 led less Foto 05-12-17 20 52 32.jpg

Then I start making something like this, but I dont get it working. It does really strange things:
Code:
#include <FastLED.h>
#define DATA_PIN 2
#define CMD_NEW_DATA 1
#define BAUD_RATE 115200

// Params for width and height
const uint8_t kMatrixWidth = 14;
const uint8_t kMatrixHeight = 26;

#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
CRGB leds[ NUM_LEDS ];
#define LAST_VISIBLE_LED 355
uint16_t XY (uint16_t x, uint16_t y) {
  // any out of bounds address maps to the first hidden pixel
  if ( (x >= kMatrixWidth) || (y >= kMatrixHeight) ) {
    return (LAST_VISIBLE_LED + 1);
  }

  const uint16_t XYTable[] = {
     0,  51,  52, 103, 356, 357, 358, 361, 362, 363, 252, 303, 304, 355,
     1,  50,  53, 102, 104, 153, 359, 360, 202, 251, 253, 302, 305, 354,
     2,  49,  54, 101, 105, 152, 154, 201, 203, 250, 254, 301, 306, 353,
     3,  48,  55, 100, 106, 151, 155, 200, 204, 249, 255, 300, 307, 352,
     4,  47,  56,  99, 107, 150, 156, 199, 205, 248, 256, 299, 308, 351,
     5,  46,  57,  98, 108, 149, 157, 198, 206, 247, 257, 298, 309, 350,
     6,  45,  58,  97, 109, 148, 158, 197, 207, 246, 258, 297, 310, 349,
     7,  44,  59,  96, 110, 147, 159, 196, 208, 245, 259, 296, 311, 348,
     8,  43,  60,  95, 111, 146, 160, 195, 209, 244, 260, 295, 312, 347,
     9,  42,  61,  94, 112, 145, 161, 194, 210, 243, 261, 294, 313, 346,
    10,  41,  62,  93, 113, 144, 162, 193, 211, 242, 262, 293, 314, 345,
    11,  40,  63,  92, 114, 143, 163, 192, 212, 241, 263, 292, 315, 344,
    12,  39,  64,  91, 115, 142, 164, 191, 213, 240, 264, 291, 316, 343,
    13,  38,  65,  90, 116, 141, 165, 190, 214, 239, 265, 290, 317, 342,
    14,  37,  66,  89, 117, 140, 166, 189, 215, 238, 266, 289, 318, 341,
    15,  36,  67,  88, 118, 139, 167, 188, 216, 237, 267, 288, 319, 340,
    16,  35,  68,  87, 119, 138, 168, 187, 217, 236, 268, 287, 320, 339,
    17,  34,  69,  86, 120, 137, 169, 186, 218, 235, 269, 286, 321, 338,
    18,  33,  70,  85, 121, 136, 170, 185, 219, 234, 270, 285, 322, 337,
    19,  32,  71,  84, 122, 135, 171, 184, 220, 233, 271, 284, 323, 336,
    20,  31,  72,  83, 123, 134, 172, 183, 221, 232, 272, 283, 324, 335,
    21,  30,  73,  82, 124, 133, 173, 182, 222, 231, 273, 282, 325, 334,
    22,  29,  74,  81, 125, 132, 174, 181, 223, 230, 274, 281, 326, 333,
    23,  28,  75,  80, 126, 131, 175, 180, 224, 229, 275, 280, 327, 332,
    24,  27,  76,  79, 127, 130, 176, 179, 225, 228, 276, 279, 328, 331,
    25,  26,  77,  78, 128, 129, 177, 178, 226, 227, 277, 278, 329, 330
  };

  uint16_t i = (y * kMatrixWidth) + x;
  uint16_t j = XYTable[i];
  return j;
}

void setup() {
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  Serial.begin(BAUD_RATE);
}
int serialGlediator () {
  while (!Serial.available()) {}
  return Serial.read();
}
void loop() {
  while (serialGlediator () != CMD_NEW_DATA) {}

  for( byte y = 0; y < kMatrixHeight; y++) {
    for( byte x = 0; x < kMatrixWidth; x++) {
      //Serial.print(XY(x,y));Serial.print("\n");    
      //leds[ XY(x, y)]  = CHSV( 10, 10, 10);
      Serial.readBytes( (char*)(&leds[ XY(x, y)]), 3);
    }
  }
  FastLED.show();
  
}

How can I get that X and Y working and map those pixels? :S
 
I was thinking about something like this but its not working:
Code:
char in_data_prt[3];
  Serial.readBytes(in_data_prt, 3);  
  //This doesnt work exactly but need to get led from serial and map to x and y??
  for( byte y = 0; y < kMatrixHeight; y++) {
    for( byte x = 0; x < kMatrixWidth; x++) {
      //Serial.print(XY(x,y));Serial.print("\n");    
      leds[ XY(x, y)]  = in_data_prt[XY(x,y)];
      //Serial.readBytes( (char*)(&leds[ XY(x, y)]), 3);
    }
  }
  FastLED.show();

Can anybody help me or point me in a direction?? :)
 
I now made this:
Code:
//
// chain all the led strips so they face the same
#include <FastLED.h>
#define NUM_LEDS 364                          //Matrix size input 24X19 pixel
#define DATA_PIN 2
#define BAUD_RATE 115200
byte colourStore[NUM_LEDS *3];


int chestLeds[] = {
  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,
  26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
  52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,
  78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,
  105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,
  130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,
  158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,
  183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,
  209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
  234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,
  260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,
  286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,
  312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,
  338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,
};


CRGB leds[NUM_LEDS];

void setup() { 
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  Serial.begin(BAUD_RATE);
}

int serialGlediator() {
  while (!Serial.available()) {}
  return Serial.read();
}

void loop() {
  while (serialGlediator() != 1) {} 
  
  for (int i=0; i < NUM_LEDS; i++) {
    leds[i].r = serialGlediator();
    leds[i].g = serialGlediator();
    leds[i].b = serialGlediator();
  }
  
  for(int x=0;x<355;x++) {
    leds[x]= leds[chestLeds[x]]; 
  }
  
  FastLED.show();
}

In the array I removed the leds what are not used by this excelsheet see the yellow marked ones:
ss+(2017-12-07+at+08.40.00).png

And it seems to work! :O

So chest done now the rest haha
 
Last edited:
Lots of ways to expand your array, but a simple one is to basically stack vertically. So your next pieace is below your current one (assuming glediator scans left right/top down). then declare a second CRGB leds[NUM_LEDS]; as say CRGB leds2[NUM_LEDS]; and declare another fastled array on your new pin. Test it with a test pattern to confirm multiple fastled versions work.

increase your iteration routine
for (int i=0; i < NUM_LEDS; i++) {
to
for (int i=0; i < NUM_LEDS*2; i++) {


then look at:

leds.r = serialGlediator();
leds.g = serialGlediator();
leds.b = serialGlediator();

bit by wrapping it in an IF
if (i<torsoLEDCount){
leds.r = serialGlediator();
leds.g = serialGlediator();
leds.b = serialGlediator();
} else
{
leds2[i-torsoLEDCount].r = serialGlediator();
leds[i-torsoLEDCount].g = serialGlediator();
leds[i-torsoLEDCount].b = serialGlediator();
}
Which should be putting the second half of the glediator data into the leds2 array, starting from location 0. You will then need to remap it like the leds array.

This is imperfect in a number of ways but the concept is consistent, and the concept works with a number of smarter packing arrangements where you trade IF statement complexity for better memory usage.

Do watch your memory reported at compile time since this process will be hungry both for program flash and RAM and fail in interesting ways, especially RAM exhaustion when feeding serial data in.
 
Thank you. I'm now first fixing only the chest and I want to play a animation from SD card instead of from Serial USB input. With serial usb input I can select the order inside Glediator to be VS_TL but when I record the animations it always saves a horizontal snake top left (HS_TL) I also tried JINX but that also save it as a (HS_TL)

Now I first need to map my for loop from a horizontal to a vertical snake, but I really dont know how to do this. This is my input code now:
Code:
while (fxdata.available())
  {
    //fxdata.readBytes((char*)leds, NUM_LEDS*3);
     for (int i=0; i < NUM_LEDS; i++) {
      leds[i].r = fxdata.read();
      leds[i].g = fxdata.read();
      leds[i].b = fxdata.read();
    }
    
    //ledSort(1);  //1-4 possible, set your first LED's position. Change the number: 1=TL(top left),2=TR(top right),3=BL(bottom left),4=BR(bottom right)
     FastLED.show();
    delay(150); // set the speed of the animation. 20 is appx ~ 500k bauds
  }
int ledSort (int modus) { //1=TL,2=TR,3=BL,4=BR, this function will rearrange the led array ;-)
    CRGB tmp[x];
    if(modus == 3 || modus == 4) {

	for(int i = 0; i < (y / 2);i++) {
	    for(int j = 0; j < x;j++) {
		tmp[j] = leds[i * x + j];
		leds[i * x] = leds[(y - i - 1) * x];
		leds[(y - i - 1) * x] = tmp[j];
	     }
        }
     }

     if(modus == 1 || modus == 3) {
       for(int i = 1; i < y; i = i + 2) {
       for(int j = x; j > 0;j--) {
        tmp[(x - j)] = leds[i * x + j - 1];
          }
           for(int j = 0; j < x;j++) {
	    leds[i * x + j] = tmp[j];
	    }
       }

      }


     if(modus == 2 | modus == 4) {
      for(int i = 0; i < y; i = i + 2) {
       for(int j = x; j > 0;j--) {
        tmp[(x - j)] = leds[i * x + j - 1];
          }
           for(int j = 0; j < x;j++) {
	    leds[i * x + j] = tmp[j];
	    }
       }

      }
      return 1;
}

That ledsort function I found on the internet but its only to set top, bottom etc not change horizontal to vertical. How to do this? :)
 
Somebody told me I need to go back to basic.

The data from SD car is a horizontal snake so
1,2,3,4,5
9,8,7,6,4

Need to convert that to vertical 2d array
1,3,5,7,9
2,4,6,8

And then loop that 3d array and use the 2d array mapper https://macetech.github.io/FastLED-XY-Map-Generator/

Can anybody help me convert 1d array to 2d array and make it vertical instead of horizontal? Really dont know the maths for this.
 
that page you linked has vertical option . create a sample array and look at the code that is created.
 
Yes I now have this code, but somehow the mapping is not correct :S The input is horizontal snake and want to convert it to vertical snake with the XYTable in top.
Code:
#include <FastLED.h>
#include <SPI.h>
#include <SD.h>

#define NUM_LEDS 364 // LED number
#define DATA_PIN 2    // your data arduino pin
#define CHIPSET WS2811  // your LED chip type
#define CMD_NEW_DATA 1
//#define BAUD_RATE 500000  //if using Glediator via serial

File fxdata;
CRGB leds[NUM_LEDS];
CRGB tmp[NUM_LEDS];

const uint16_t XYTable[] = {
     0,  51,  52, 103, 104, 155, 156, 207, 208, 259, 260, 311, 312, 363,
     1,  50,  53, 102, 105, 154, 157, 206, 209, 258, 261, 310, 313, 362,
     2,  49,  54, 101, 106, 153, 158, 205, 210, 257, 262, 309, 314, 361,
     3,  48,  55, 100, 107, 152, 159, 204, 211, 256, 263, 308, 315, 360,
     4,  47,  56,  99, 108, 151, 160, 203, 212, 255, 264, 307, 316, 359,
     5,  46,  57,  98, 109, 150, 161, 202, 213, 254, 265, 306, 317, 358,
     6,  45,  58,  97, 110, 149, 162, 201, 214, 253, 266, 305, 318, 357,
     7,  44,  59,  96, 111, 148, 163, 200, 215, 252, 267, 304, 319, 356,
     8,  43,  60,  95, 112, 147, 164, 199, 216, 251, 268, 303, 320, 355,
     9,  42,  61,  94, 113, 146, 165, 198, 217, 250, 269, 302, 321, 354,
    10,  41,  62,  93, 114, 145, 166, 197, 218, 249, 270, 301, 322, 353,
    11,  40,  63,  92, 115, 144, 167, 196, 219, 248, 271, 300, 323, 352,
    12,  39,  64,  91, 116, 143, 168, 195, 220, 247, 272, 299, 324, 351,
    13,  38,  65,  90, 117, 142, 169, 194, 221, 246, 273, 298, 325, 350,
    14,  37,  66,  89, 118, 141, 170, 193, 222, 245, 274, 297, 326, 349,
    15,  36,  67,  88, 119, 140, 171, 192, 223, 244, 275, 296, 327, 348,
    16,  35,  68,  87, 120, 139, 172, 191, 224, 243, 276, 295, 328, 347,
    17,  34,  69,  86, 121, 138, 173, 190, 225, 242, 277, 294, 329, 346,
    18,  33,  70,  85, 122, 137, 174, 189, 226, 241, 278, 293, 330, 345,
    19,  32,  71,  84, 123, 136, 175, 188, 227, 240, 279, 292, 331, 344,
    20,  31,  72,  83, 124, 135, 176, 187, 228, 239, 280, 291, 332, 343,
    21,  30,  73,  82, 125, 134, 177, 186, 229, 238, 281, 290, 333, 342,
    22,  29,  74,  81, 126, 133, 178, 185, 230, 237, 282, 289, 334, 341,
    23,  28,  75,  80, 127, 132, 179, 184, 231, 236, 283, 288, 335, 340,
    24,  27,  76,  79, 128, 131, 180, 183, 232, 235, 284, 287, 336, 339,
    25,  26,  77,  78, 129, 130, 181, 182, 233, 234, 285, 286, 337, 338
};

void setup()
{
  FastLED.addLeds<CHIPSET, DATA_PIN, GRB>(leds, NUM_LEDS); //see doc for different LED strips
  FastLED.setBrightness(30);
  //  Serial.begin(BAUD_RATE); // when using Glediator via usb
  Serial.begin(115200);

  for (int y = 0 ; y < NUM_LEDS ; y++)
  {
    leds[y] = CRGB::Black; // set all leds to black during setup
  }
  FastLED.show();

  pinMode(10, OUTPUT); // CS/SS pin as output for SD library to work.
  digitalWrite(10, HIGH); // workaround for sdcard failed error...

  if (!SD.begin(BUILTIN_SDCARD))
  {
    Serial.println("sdcard initialization failed!");
    return;
  }
  Serial.println("sdcard initialization done.");

  // test file open
  fxdata = SD.open("testje.dat");  // read only
  if (fxdata)
  {
    Serial.println("file open ok");
    fxdata.close();
  }
}

int serialGlediator ()
{
  while (!Serial.available()) {}
  return Serial.read();
}

void loop()
{
  fxdata = SD.open("testje.dat");  // read only
  if (fxdata)
  {
    Serial.println("file open ok");
  }

  while (fxdata.available())
  {
    for (int i=0; i < NUM_LEDS; i++) {
      tmp[i].r = fxdata.read();
      tmp[i].g = fxdata.read();
      tmp[i].b = fxdata.read();
    }
    //fxdata.readBytes((char*)leds, NUM_LEDS * 3);

    tmp[20].g=200;
    //tmp[2].b=255;

    for (int i=0; i < NUM_LEDS; i++) {
      //leds[i] = tmp[i];
      
      leds[i] = tmp[XYTable[i]];

      Serial.print(i);
      Serial.print(" = ");
      Serial.print(XYTable[i]);
      Serial.print(" = ");
      Serial.print(tmp[i]);
      //Serial.print(tmp[XYTable[i]].g);
      //Serial.print(tmp[XYTable[i]].b);
      Serial.println();
    }

    //leds[5] = CRGB::Red;
    //leds[10] = CRGB::Red;
    
    FastLED.show();
    delay(150);
  }
  fxdata.close();

  
}

Even when I replace tmp.r = fxdata.read(); with 0;// and only set tmp[2] to red and do it the red led of 2 is not moved to 52
 
What does the output of your debug print functions look like?

To help keep those under control suggest putting the prints inside an if (i<52) check so you don't have 400 odd lines to look at and also avoid trouble because USB serial fell over with to much data. If you want to dump your actual LED array values in the same format as the XYtable you can also change your println to
if (i%14==13) println();
Modulo(%) returns the remainder for dividing a number by another, so 14%14 returns 0 because 14 divides into 14 with 1 and zero left over, but 13,27,41 etc will all return 13, because they are 0,1,2 from the divide with 13 left over. A very handy function when doing array manipulation like this.
If you can't fit your debug onto a single 14 entry line you could also split it in half by doing println on %13 but also adding
if (i%14==6) {println(); print(" ");}
which will break your 14 line debug into two rows of 7 where the second line has a couple of spaces at the start to break up the wall of numbers into even/odd.
 
Yes, I fixed it now. At first I was thinking wrong. I was mapping the loop with the XYTable but I must map the XYTable with the loop instead. Also the data from sd card was horizontal but not Serpentine. So I modified the XYTable and it works now :D

This is my running code for 1 inregular panel:
Code:
#include <FastLED.h>
#include <SPI.h>
#include <SD.h>

#define NUM_LEDS 364 // LED number
#define DATA_PIN 2    // your data arduino pin
#define CHIPSET WS2811  // your LED chip type
#define CMD_NEW_DATA 1
//#define BAUD_RATE 500000  //if using Glediator via serial

File fxdata;
CRGB leds[NUM_LEDS];
CRGB tmp[NUM_LEDS];

const uint16_t XYTable[] = {
     0,  51,  52, 103, 104, 155, 156, 207, 208, 259, 260, 311, 312, 363,
     1,  50,  53, 102, 105, 154, 157, 206, 209, 258, 261, 310, 313, 362,
     2,  49,  54, 101, 106, 153, 158, 205, 210, 257, 262, 309, 314, 361,
     3,  48,  55, 100, 107, 152, 159, 204, 211, 256, 263, 308, 315, 360,
     4,  47,  56,  99, 108, 151, 160, 203, 212, 255, 264, 307, 316, 359,
     5,  46,  57,  98, 109, 150, 161, 202, 213, 254, 265, 306, 317, 358,
     6,  45,  58,  97, 110, 149, 162, 201, 214, 253, 266, 305, 318, 357,
     7,  44,  59,  96, 111, 148, 163, 200, 215, 252, 267, 304, 319, 356,
     8,  43,  60,  95, 112, 147, 164, 199, 216, 251, 268, 303, 320, 355,
     9,  42,  61,  94, 113, 146, 165, 198, 217, 250, 269, 302, 321, 354,
    10,  41,  62,  93, 114, 145, 166, 197, 218, 249, 270, 301, 322, 353,
    11,  40,  63,  92, 115, 144, 167, 196, 219, 248, 271, 300, 323, 352,
    12,  39,  64,  91, 116, 143, 168, 195, 220, 247, 272, 299, 324, 351,
    13,  38,  65,  90, 117, 142, 169, 194, 221, 246, 273, 298, 325, 350,
    14,  37,  66,  89, 118, 141, 170, 193, 222, 245, 274, 297, 326, 349,
    15,  36,  67,  88, 119, 140, 171, 192, 223, 244, 275, 296, 327, 348,
    16,  35,  68,  87, 120, 139, 172, 191, 224, 243, 276, 295, 328, 347,
    17,  34,  69,  86, 121, 138, 173, 190, 225, 242, 277, 294, 329, 346,
    18,  33,  70,  85, 122, 137, 174, 189, 226, 241, 278, 293, 330, 345,
    19,  32,  71,  84, 123, 136, 175, 188, 227, 240, 279, 292, 331, 344,
    20,  31,  72,  83, 124, 135, 176, 187, 228, 239, 280, 291, 332, 343,
    21,  30,  73,  82, 125, 134, 177, 186, 229, 238, 281, 290, 333, 342,
    22,  29,  74,  81, 126, 133, 178, 185, 230, 237, 282, 289, 334, 341,
    23,  28,  75,  80, 127, 132, 179, 184, 231, 236, 283, 288, 335, 340,
    24,  27,  76,  79, 128, 131, 180, 183, 232, 235, 284, 287, 336, 339,
    25,  26,  77,  78, 129, 130, 181, 182, 233, 234, 285, 286, 337, 338
};

int chestLeds[] = {
  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,
  26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
  52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,
  78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,
  105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,
  130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,
  158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,
  183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,
  209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
  234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,
  260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,
  286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,
  312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,
  338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,
};

void setup()
{
  FastLED.addLeds<CHIPSET, DATA_PIN, GRB>(leds, NUM_LEDS); //see doc for different LED strips
  FastLED.setBrightness(65);
  //  Serial.begin(BAUD_RATE); // when using Glediator via usb
  Serial.begin(115200);

  for (int y = 0 ; y < NUM_LEDS ; y++)
  {
    leds[y] = CRGB::Black; // set all leds to black during setup
  }
  FastLED.show();

  pinMode(10, OUTPUT); // CS/SS pin as output for SD library to work.
  digitalWrite(10, HIGH); // workaround for sdcard failed error...

  if (!SD.begin(BUILTIN_SDCARD))
  {
    Serial.println("sdcard initialization failed!");
    return;
  }
  Serial.println("sdcard initialization done.");

  // test file open
  fxdata = SD.open("testje.dat");  // read only
  if (fxdata)
  {
    Serial.println("file open ok");
    fxdata.close();
  }
}

int serialGlediator ()
{
  while (!Serial.available()) {}
  return Serial.read();
}

void loop()
{
  fxdata = SD.open("dwain.dat");  // read only
  if (fxdata)
  {
    Serial.println("file open ok");
  }

  while (fxdata.available())
  {
    for (int i=0; i < NUM_LEDS; i++) {
      tmp[i].r = fxdata.read();
      tmp[i].g = fxdata.read();
      tmp[i].b = fxdata.read();
    }
    //fxdata.readBytes((char*)leds, NUM_LEDS * 3);

    for (int i=0; i < NUM_LEDS; i++) {
      //leds[i] = tmp[i];
      
      leds[XYTable[i]] = tmp[i];

      Serial.print(i);
      Serial.print(" = ");
      Serial.print(XYTable2[i]);
      Serial.print(" = ");
      Serial.print(tmp[i]);
      Serial.println();
      //Serial.print(tmp[XYTable[i]].g);
      //Serial.print(tmp[XYTable[i]].b);
      //if (i%14==13) Serial.println();
    }

    for(int x=0;x<355;x++) {
      leds[x]= leds[chestLeds[x]]; 
    }
    
    FastLED.show();
    delay(150);
  }
  fxdata.close();

  
}

Now I'm going to soldern the top right shoulder because that will be starting point of whole led panel (0). So total max width and height is like 40x40 or so and need to get left arm is led 0 - 400 but also need to split the half of that for top arm and bottom arm. Like 0-10 is top arm, 10-20 is bottom arm, 20-30 is top arm, 30-40 is bottom arm.
 
I have worked on the code the whole evening yesterday and I found a way to make it work for me. My question: Is it the best way?

What i'm thinking of:
- Make a led panel in glediator with total width*height of the whole suit (think all panels are 1 panel)

- Load all the leds in from serial like
Code:
fxdata.readBytes((char*)leds, NUM_LEDS * 3);

- Then make a for loop for each panel so for example panel top left shoulder has 70 leds for loop 0-70 and then make a array and match it:
Code:
for(int x=0;x<70;x++) {
      panelTopLeftShoulder[x]= leds[topLeftShoulderArray[x]]; 
    }

In that array I set that led 0 from topleftshoulder = led 50 from the panel for example. so 0=50, 1=51, 2=52 etc.

Its a fast and easy way without using any if/else function on count or x and y. I only have then 10 for loops to loop the leds of each panel.

What do u guys think about this option? For me its the best and easiest solution.
 
Status
Not open for further replies.
Back
Top