Arduino > NeoPixels

1.  Introduction

«One of the most popular NeoPixel form-factors is the 60 LED/meter flex strip. NeoPixel data is clocked at 800 KHz…that’s 1.25 microseconds/bit, or 30 microseconds per 24-bit pixel. One meter of this strip (60 NeoPixels) therefore takes 1,800 microseconds to refresh (not counting the 50 to 300 microsecond latch time at the end of the data, which is the same regardless of strip length), so we could estimate that NeoPixel data (at this particular strip density) travels at about 555.555 meters/second. » https://blog.adafruit.com/2017/12/12/neopixels-five-years-in-adafruit-neopixels/

2.  Alimentation

3.  Branchement

4.  Logithèques

4.1  Adafruit Neopixel (plus facile)

4.2  FastLed (plus performante)

4.3  WS2812FX

This library features a variety of blinken effects for the WS2811/WS2812/NeoPixel LEDs. It is meant to be a drop-in replacement for the Adafruit NeoPixel library with additional features. https://github.com/kitesurfer1404/WS2812FX#effects

5.  Correction gamma

https://learn.adafruit.com/led-tricks-gamma-correction/the-issue

6.  Code de base (Neopixel)

// Global:
#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
// In setup:
pixels.begin();
// Create a color:
int color = pixels.Color( red , green , blue );
// Set a pixel:
pixels.setPixelColor(i, color );
// Update the pixels on the strip with the new values:
pixels.show();
// Clear all pixels
pixels.clear();

7.  Exemples

7.1  Exemple de base


#include <Adafruit_NeoPixel.h>

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIXELS_PIN 6

// How many NeoPixels are attached to the Arduino?
#define NUM_PIXELS 58

// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, PIXELS_PIN, NEO_GRB + NEO_KHZ800);

// Include Chrono:
#include <Chrono.h>
Chrono pixelsChrono; // A timer for the graphics update

void setup() {

        // Initialize the NeoPixel library:
        pixels.begin();

        // Seed the random:
        randomSeed( analogRead(0) + analogRead(1) + analogRead(2) + analogRead(3) + analogRead(4) + analogRead(5));

}

void loop() {


        // Update sensors here (if you have sensors).

        // Send data to computer here (if you have data to send).

        // Receive data from computer here (if you have data to receive).

        // Update the graphics 50 times per second :
        if ( pixelsChrono.hasPassed(20) ) {
                pixelsChrono.restart();

                pixels.clear(); // Clear previous data if necessary.

                // Draw pixels :
                int color = pixels.Color(255, 255, 255);
                pixels.setPixelColor(0, color );

                pixels.show(); // Send the updated pixels to the hardware.
        }


}

7.2  Méga démo

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

#define PIN 6

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.

void setup() {
        // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
        #if defined (__AVR_ATtiny85__)
        if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
        #endif
        // End of trinket special code


        strip.begin();
        strip.show(); // Initialize all pixels to 'off'
}

void loop() {
        // Some example procedures showing how to display to the pixels:
        colorWipe(strip.Color(255, 0, 0), 50); // Red
        colorWipe(strip.Color(0, 255, 0), 50); // Green
        colorWipe(strip.Color(0, 0, 255), 50); // Blue
        //colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW
        // Send a theater pixel chase in...
        theaterChase(strip.Color(127, 127, 127), 50); // White
        theaterChase(strip.Color(127, 0, 0), 50); // Red
        theaterChase(strip.Color(0, 0, 127), 50); // Blue

        rainbow(20);
        rainbowCycle(20);
        theaterChaseRainbow(50);
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
        for(uint16_t i=0; i<strip.numPixels(); i++) {
                strip.setPixelColor(i, c);
                strip.show();
                delay(wait);
        }
}

void rainbow(uint8_t wait) {
        uint16_t i, j;

        for(j=0; j<256; j++) {
                for(i=0; i<strip.numPixels(); i++) {
                        strip.setPixelColor(i, Wheel((i+j) & 255));
                }
                strip.show();
                delay(wait);
        }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
        uint16_t i, j;

        for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
                for(i=0; i< strip.numPixels(); i++) {
                        strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
                }
                strip.show();
                delay(wait);
        }
}

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
        for (int j=0; j<10; j++) {  //do 10 cycles of chasing
                for (int q=0; q < 3; q++) {
                        for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
                                strip.setPixelColor(i+q, c);    //turn every third pixel on
                        }
                        strip.show();

                        delay(wait);

                        for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
                                strip.setPixelColor(i+q, 0);        //turn every third pixel off
                        }
                }
        }
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
        for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
                for (int q=0; q < 3; q++) {
                        for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
                                strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
                        }
                        strip.show();

                        delay(wait);

                        for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
                                strip.setPixelColor(i+q, 0);        //turn every third pixel off
                        }
                }
        }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
        WheelPos = 255 - WheelPos;
        if(WheelPos < 85) {
                return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
        }
        if(WheelPos < 170) {
                WheelPos -= 85;
                return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
        }
        WheelPos -= 170;
        return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

7.3  Bouncing ball


#include <Adafruit_NeoPixel.h>

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIXELS_PIN 6

// How many NeoPixels are attached to the Arduino?
#define NUM_PIXELS 58

// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, PIXELS_PIN, NEO_GRB + NEO_KHZ800);

float ball_x = NUM_PIXELS / 2;
float ball_speed;

#include <Chrono.h>
Chrono updateChrono;

void setup() {

        // This initializes the NeoPixel library.
        pixels.begin();

        // Seed the random
        randomSeed( analogRead(0) + analogRead(1) + analogRead(2) + analogRead(3) + analogRead(4) + analogRead(5));

        // Random ball direction
        if ( random(2) == 1 ) {
                ball_speed = -1;
        } else {
                ball_speed = 1;
        }

}

void loop() {

        if ( updateChrono.hasPassed(20) ) {
                updateChrono.restart();

                ball_x = ball_x + ball_speed;

                if ( ball_x >= NUM_PIXELS-1 )  {
                        ball_x = NUM_PIXELS - 2 ;
                        ball_speed = -ball_speed;
                }

                if ( ball_x < 0 ) {
                        ball_x = 1;
                        ball_speed = -ball_speed;
                }

                pixels.clear();

                pixels.setPixelColor(floor(ball_x), pixels.Color(255, 255, 255));

                pixels.show(); // This sends the updated pixel color to the hardware.
        }


}

7.4  Pong

#include <Adafruit_NeoPixel.h>

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIXELS_PIN            6

// How many NeoPixels are attached to the Arduino?
#define NUM_PIXELS      60

// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, PIXELS_PIN, NEO_GRB + NEO_KHZ800);

float ball_x ;
float ball_speed;

#include <Chrono.h>
Chrono updateChrono;

#include <Bounce2.h>
Bounce buttonLeft;
Bounce buttonRight;

int highlightLeftZone = 0;
int highlightRightZone = 0;


void setup() {

        // This initializes the NeoPixel library.
        pixels.begin();


        // Seed the random
        randomSeed( analogRead(0) + analogRead(1) + analogRead(2) + analogRead(3) + analogRead(4) + analogRead(5));

        pinMode(2, INPUT_PULLUP);
        buttonLeft.attach(2);

        pinMode(3, INPUT_PULLUP);
        buttonRight.attach(3);

        startGame();


}

void startGame() {

        ball_x = NUM_PIXELS / 2;

        // Random ball direction
        if ( random(2) == 1 ) {
                ball_speed = -0.25;
        } else {
                ball_speed = 0.25;
        }
}

void leftWins() {
        pixels.clear();

        for ( int i = 0; i < NUM_PIXELS / 2 ; i++ ) {
                pixels.setPixelColor(i, pixels.Color(255, 0, 0));
        }



        pixels.show(); // This sends the updated pixel color to the hardware.
        delay(2000);
        startGame();
}

void rightWins() {
        pixels.clear();

        for ( int i = NUM_PIXELS / 2; i < NUM_PIXELS ; i++ ) {
                pixels.setPixelColor(i, pixels.Color(255, 0, 0));
        }

        pixels.show(); // This sends the updated pixel color to the hardware.
        delay(2000);
        startGame();
}

void setField() {


        for ( int i = NUM_PIXELS - 10 ; i < NUM_PIXELS ; i++ )  {
                pixels.setPixelColor(i, pixels.Color(0, 12 + highlightLeftZone, 0));
        }
        highlightLeftZone = highlightLeftZone - 10;
        if (highlightLeftZone < 0) highlightLeftZone = 0;

        for ( int i = 0 ; i < 10 ; i++ ) {
                pixels.setPixelColor(i, pixels.Color(0, 12 + highlightRightZone, 0));
        }
        highlightRightZone = highlightRightZone - 10;
        if (highlightRightZone < 0) highlightRightZone = 0;
}


void loop() {

        buttonLeft.update();
        buttonRight.update();

        if ( buttonLeft.fell() ) {
                if ( ball_x > ( NUM_PIXELS - 10) ) {
                        ball_speed = -ball_speed;
                        ball_speed = ball_speed * 1.1;
                        highlightLeftZone = 243;
                } else {
                        rightWins();
                }
        }

        if ( buttonRight.fell() ) {
                if ( ball_x < 10 ) {
                        ball_speed = -ball_speed;
                        ball_speed = ball_speed * 1.1;
                        highlightRightZone = 243;
                } else {
                        leftWins();
                }
        }


        if ( updateChrono.hasPassed(10) ) {
                updateChrono.restart();

                ball_x = ball_x + ball_speed;

                if ( ball_x >= 0 && ball_x < NUM_PIXELS - 1) {

                        pixels.clear();
                        setField();
                        pixels.setPixelColor(floor(ball_x), pixels.Color(255, 255, 255));
                        pixels.show(); // This sends the updated pixel color to the hardware.

                } else {


                        if ( ball_x >= NUM_PIXELS - 1  )  {
                                rightWins();
                        } else if ( ball_x < 0 ) {
                                leftWins();
                        }

                }
        }

}

7.5  Roche, papier, ciseaux

Des pixels de couleur aléatoire (rouge, vert, bleu ou vide) sont générés à chaque bout d'une guirlande de 60 DEL RGB. Ces pixels avancent vers un point de rencontre initialement au centre. Au point de rencontre, les pixels se battent à «roche, papier, ciseaux» (rouge bat vert, vert bat bleu, bleu bas rouge, toutes les couleurs battent le vide). Le point de rencontre se rapproche alors du perdant.

#include <Adafruit_NeoPixel.h>

#define VIDE 0
#define ROUGE 1
#define VERT 2
#define BLEU 3

int couleurs[60];


int pointCentral = 30;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(60, 6, NEO_GRB + NEO_KHZ800);


void setup() {
        // put your setup code here, to run once:
        pixels.begin(); // This initializes the NeoPixel library.

}

void loop() {
        // put your main code here, to run repeatedly:

        couleurs[0] = random(0, 4);
        couleurs[59] = random(0, 4);

        // mettre a jour le point central
        int coteDroit = couleurs[pointCentral - 1];
        int coteGauche = couleurs[pointCentral + 1];

        if ( coteDroit == ROUGE && (coteGauche == VERT ||  coteGauche == VIDE )) {
                pointCentral++;
        } else if ( coteDroit == VERT && (coteGauche == BLEU ||  coteGauche == VIDE )) {
                pointCentral++;
        } else  if ( coteDroit == BLEU && (coteGauche == ROUGE ||  coteGauche == VIDE )) {
                pointCentral++;
        }

        if ( coteGauche == ROUGE && (coteDroit == VERT ||  coteDroit == VIDE )) {
                pointCentral--;
        } else if ( coteGauche == VERT && (coteDroit == BLEU ||  coteDroit == VIDE )) {
                pointCentral--;
        } else  if ( coteGauche == BLEU && (coteDroit == ROUGE ||  coteDroit == VIDE )) {
                pointCentral--;
        }

        if ( pointCentral > 57 ) pointCentral = 57;
        if ( pointCentral < 2 ) pointCentral = 2;


        for ( int i = pointCentral - 1 ; i >= 0  ; i-- ) {
                couleurs[i + 1] = couleurs[i];

        }


        for ( int i = pointCentral + 1 ; i < 60 ; i++ ) {
                couleurs[i - 1] = couleurs[i];
        }

        for (int i = 0; i < 60; i++) {
                int c = couleurs[i];
                if ( c == VIDE ) {
                        pixels.setPixelColor(i, pixels.Color(0, 0, 0)); // Moderately bright green color.
                } else if ( c == ROUGE ) {
                        pixels.setPixelColor(i, pixels.Color(255, 0, 0)); // Moderately bright green color.
                } else if ( c == VERT ) {
                        pixels.setPixelColor(i, pixels.Color(0, 255, 0)); // Moderately bright green color.
                } else if ( c == BLEU ) {
                        pixels.setPixelColor(i, pixels.Color(0, 0, 255)); // Moderately bright green color.
                }
        }
        pixels.setPixelColor( pointCentral, pixels.Color(255, 255, 255));
        pixels.show();

        delay(100);

}

7.6  Projectiles

Un projectile de couleur et de vitesse aléatoire traverse la bande à chaque intervalle de temps. Télécharger le projet ici : fastled_projectiles.zip

7.7  Explosions

Une animation se déclenche avec une position aléatoire à chaque intervalle de temps. Télécharger le projet ici : fastled_explosions.zip

8.  Exemples contrôlés par logiciels

8.1  Contrôle par UDP (ESP8266/Wemos)

Code Arduino

// INCLUDE ESP8266WiFi:
#include <ESP8266WiFi.h>

// SETUP NETWORK
const char* ssid     = "ssid";
const char* password = "password";
IPAddress myIp(192, 168, 1, 12);
IPAddress networkGateway(192, 168, 1, 1);
IPAddress networkSubnet(255, 255, 255, 0);

int myPort = 7777; // UDP LISTEN
IPAddress targetIp = IPAddress(192, 168, 25, 125); // UDP SEND
int targetPort = 7890; // UDP SEND

// SPECIAL LINE FOR ESP8266 DEVICES :
#define FASTLED_ESP8266_NODEMCU_PIN_ORDER
/*
https://github.com/FastLED/FastLED/wiki/ESP8266-notes
*/

#include <Chrono.h>
Chrono blinkChrono;
Chrono updateLedsChrono;

#include <FastLED.h>
#define NUM_LEDS 41

CRGBArray<NUM_LEDS> leds;


CRGB initialColor = CRGB( 150, 55, 255);




// INCLUDE ESP8266 UDP
#include <WiFiUdp.h>
WiFiUDP udp;

// SET COLOR TEMPERATURE
// https://github.com/FastLED/FastLED/blob/master/examples/ColorTemperature/ColorTemperature.ino

void setup() {
        FastLED.addLeds<NEOPIXEL, 3>(leds, NUM_LEDS);
        fill_solid( leds, NUM_LEDS, initialColor);
        FastLED.show();

        delay(1000);
        FastLED.show();

        pinMode(LED_BUILTIN, OUTPUT);
        digitalWrite(LED_BUILTIN, HIGH);

        // INITIATE SERIAL COMMUNICATION FOR DEBUGGING.
        Serial.begin(57600);

        // BEGIN WIFI
        WiFi.config(myIp , networkGateway , networkSubnet );
        WiFi.begin(ssid, password);


        // WAIT UNTIL CONNECTED
        while (WiFi.status() != WL_CONNECTED) {
                Serial.print(".");
                delay(250);
                digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
        }
        //
        digitalWrite(LED_BUILTIN, HIGH);

        // PRINT CONNECTION SETTINGS
        Serial.println();
        Serial.println("WiFi connected, IP address: ");
        Serial.println( WiFi.localIP() );
        //


        udp.begin(myPort); // BEGIN LISTENING ON UDP PORT myPort

}



void loop() {


        int packetSize = udp.parsePacket();
        if ( packetSize > 0 ) {
                blinkChrono.restart();
                digitalWrite(LED_BUILTIN, LOW);

                if ( packetSize == 3 ) {
                        char r =  udp.read();
                        char g =  udp.read();
                        char b =  udp.read();

                        CRGB color = CRGB( r, g, b);

                        fill_solid( leds, NUM_LEDS, color);

                        FastLED.show();

                } else  {


                        int pixelsReceived = packetSize / 3;
                        for (int i = 0; i < pixelsReceived && i < NUM_LEDS ; i++) {


                                // let's set an led value
                                char r =  udp.read();
                                char g =  udp.read();
                                char b =  udp.read();
                                leds[i].setRGB( r , g , b );
                                yield();

                        }
                        FastLED.show();
                }
        }

        if ( blinkChrono.hasPassed(25) ) {
                digitalWrite(LED_BUILTIN, HIGH);
        }

}


Code Max

<pre><code>
----------begin_max5_patcher----------
3095.3oc6b01iaiaD9ya.t+CDF8acqq3a5k9o6RQQPAtd8PtBTTDbvP1h1qx
IKIHIu6lbn+26LjR1RxRxZ8Z4cSSBxZIyWm4gCGNb3P+6e2atY1xjGU4yH+E
xGH2byuCobiNMLkapR3lYa8ebUjettfyhUOjr7iytsLuB0iE5zSIeLrX9V+h
rvGWTjrHJLuXeoh2sMYWQjpP2FzpjMoU7oTkgFlMi7qU4EFnaVnu9Sb28MTp
ewp6Bi2rHSspvTIgMet0sDaKG7A0hhOXr4VGZKn6CiOp20skJqjYq31alsNL
RcuJKOLItd4uYleZZszuodkPP5iI51x81CoEFaRy5PZYp6COpog1NC3qBfo1
koAiYOZKlUqkRBTYw6B00pL0+628l8jld7I1eqJO0ekoAvww84e.trP3Q+gs
P+P3ZUCqfw+MQIq9MUPC5dVRpJNLNMSkqhK7KJYfC4GnV6uKpXw5j3h7vOqI
AJLHzYAVWRicmKxFZN3GxB8iNvCaxBCRhQBo4vBldUW9ABUpECjM3IcQh8S6
p5fDF.N8kaNvr6xW5mgiZKizcBaetEIIQMy6PMiTqKJyOMLNtMfVjjNPtYga
tanZuLAxc6fMuNq7E6hMYu.jPJVj6eeKjuvOJpbNcqd3Q+3PX9rpHzLdvrNj
qJ1GX36xWkkDE0juMYceWYE.x9qTODFTbmtyZHd.UHLsRvZ1gg8fvMp7hVIV
3uIuUR4EexLDTOscKKmkunPsMMB3lVkngFvFynqqIrYFCpQroVwOGQ1jkrKs
QtM0Fxpm0wZDustVwizLxazvcnczgOWBSGb0yJjGqa7X8ir8Y.JXpdG00LI.
TAYIIh74nUQJ+rAPI9fnzR+3MZj5VDxMsU+fF6TflzxrThQMo8H.M5UEzvUZ
gEKNe7pBq5GjX1iTxhqgGyRIWcPR21CfBzAQA.FWXLXY.gE6wIrX..99OG.F
rpmypjsagUTapURSCwApGmFTy.DC.aV8AFNiSnfY6LZzfdYPiZK1GEF2qJcM
IiEnGbJOYW1pJ4iJkEDZS5GVqpHLduQPe3vLFBvoie357HF1XHFbggIlXp32
WEDiFYd0PLiGYXSOwvGMw3LHwTkwgscLCslLXgw.5E9Eflzk6JLy8Zripmnw
cvFPV5GUZ319cCzkwe6oH8KkOKAtwscVXGS49aTGueVAGVaC9SZSjtDpvF9J
k3HfTbHTpj3QITaIXkfq4OaOHYKXSOby6LHeNjuMTEN7cAVU76P5RLMnE83l
lCJKCqK9tkM7tmtLdLXIUn3BOhKVBnVBFniEMEWScNLvzN3Un73CgTSBP0nL
Kz9EMk4IMoHPp20PMPG4.8uzhHbHH0BrIPfHshLrkgmcwrPZBpgqAGXH2xIH
SPgWoPsQL.4WnIwNjUATdHioobjMgRCMgmPWX.6vbsfG151SmNVJJw0U+.wD
WYILxHtkCGvvBxBH.Jg1F5WGbbPykT8WwFT.HDz9Xkn.bhCItFhmwgz8rz.I
S3XpCvhLrEwV1wCdmqeR8JKiC1dBScADAGHXLfOsw11RmGNLa5GLct4cfBMo
irClNzOnjiaYyXoGDbvV.PWoIU.FPQCfkX.VhiiX2.o5ZZXK4dgUTOvpjclE
LozKj2VjC4sEXiDvB71RgdocOasMfR6d81B6rmYhF4l9.rvexC83GIV+b1s8
wcrA4Nao1ZVom9gqw9eq9ckzYyb84EsC9PivIqtyOC5dv7iu2OvOs.TN+86x
U4YqBB2hoZdKuvOCyypJAUbfYh591ue2pLZHslwx8Cthw.t1ZaDEtt5sLvqi
tM7dDeu6AtTndQxlMQpZzXFfIv9nVX7YQcSeG8jnPb1WmfAaDfA2VuwbGupO
uZRZ.imkfqQ7jcRqdy1cxxfd6QvyBowgs7S3n1yW0QT38p4A0kxu2+fgD6y8
C7e8.4Vyyl0HYNcNG9mivhwEbGTYGSq5SX9zsN02k7D8DyyZ6QU5f5zVGk3W
zG1O3jOGiflP51G02sSxMl3s21tgrx6d+ncpj0c3a7C.SE+Tyg3GxbWbXwdu
3Q6pDaARTm47Nafnj3MCNL2pw7Maozp6VKDHGTFx3V4ZVPWqL42kjcPyZ9Je
f3O3d9mu4o8eZKOfGWvOkDlqdxSf6xuGMEkrFidbVMUWCLMl+084sHXZSIJO
UBt9aNRuucjKe6HW91Qtbtdvri8FbgOYE5I86Ky34aaaVO6U30voD.5C25Gg
yTOWXpO69OBvjmBvnlSn21Ra3mC+E4DCtBRN7QJ4HsoufRNOuiNY.125TruM
UXF5oS0Qlvupyy9inVU9YCksrouMd5dRoIOiuXLA9hwbiWUGw65oBZNsJZl2
blbO1.eS9J73uWd1JhpN16l6HuMLINohYiAbLWyo1I9B7nbG3.bOE2y45cvP
M9iZJTGwt5K6W.7XibGvH+oxf.mQZOfTXOjhq91cyUPjr0YC0Dl060m7Gnl+
e9f84JWyN4zZoYgAgwW8dG6t0gb450PwHndG5gVrQ+tj8RKHeZMmTuSgwBGW
bMEtPu.iITP5BiAqv00v9rfd5WePO6jlQJX1eQB8Co6N0+2HIqWmqJ.aJM++
EPyxIiONtsPC8NZcJTJ+YpZQ7UnpkQq9lw++G4az1jkq2P3Dso8bl4L4wyxb
oedXNIFcn877vsoQpGeosfYrdzPZoOTbli0ybdvqnP8iMVu43wt1g52K0dLN
wD5QBXLlyWNQJJdZe6BazaXRly6.mvNENP5zHovolgsrQ4xiqcbihtCcbgcG
sinELIKvbPYVSXjANdRjM.ERmPJzYzXn7EhBGMD5L4A5oXrjhb5CM3mJsTuf
aCCRSBiKJmJhGWfNbgzyxkNk2YsFeyRaNJkp2Pf9aSK6wtbrG2QTwBrl7.aZ
YBTM6qE4kwOOm+BoqzcrTns45BLgjxnCtb2WHch7mBANsX0nkwEStLNdtXiT
H+JPLiVAM6JPLdilXPEu7oU2t0ShXXS9R5zwp0w50gVmtFMOoJ5uxtaILojT
9W2AfZi.6meYhq+CQzRmdaxwbCgMwlgbxBM2dwDL90stP+fQPGLH+klH30vp
7W.V88j2Qd6khUEC+aigyAVUPmLVsx2DGwp+q6TfB62+t2RzQGbNwuffQoGg
f93t.xsL80IY5utNLKu.pRZ3ipn7d.Iqt.hAC2dgmweKTSLmvMPwTbyN5cTG
unV3j95Oqd+5qLXvH7kYWdV3FOVQkWeAm+Yr5fXCILm.kLMIWEPRVCBJYJEA
HgkprbxRUwCJULn+vONXjvHa7BVdCFKz0lewKuQKSgTUu3z+XWTQXZjp9brG
BihJmeAS215G+oxoSjmv7oA+M2g4X74lI10jkw.9Ukw+EUb.PTjjFBJ6Y8e3
G+Qs9jRFuHw.F5R8DPAmAuSEZPvyybkw3WeUJco534oWXvENokGvgQsvW5FI
vGjUENy021GGmI1JgdEv+q24GuQYjbUj+9Oq0tkljUXz.pH+se4mcY11+4+s
ZaxSYkxAWnj44XBYtxELYuPh0kqNdoDqGbdL0DPpTyYr9RHWWylfKEGO3nrq
dTkZh.2Ijg665Kk6G3uc9tfTTKtJCuo0yofQGz4TJwA92rK10vjSOMPTJryn
Vm52NtVHgoXMO4nRjo8NrqvmS4r799wYno27Z6IuNGbFMIztw6gDjMbGQ6c0
eUHA5DhBiaffI6gDtDn.skWBGiS4dlLMaLcHs5zBtH7Hcbco0ErKEiuKYWlt
z5oHOeA5P4Ut+3Wa9y4Z2grmQGVtvPqavptuZeyUaeqU63FqNvsU8napZoKT
M2Mu1KJcH.p1EDlrMrJDqptLnsvjkaVC6mZURTxw2Z2p0dmsIyOHrlErXjp.
UfV8yMJ2wV3PweyQ4tBNUfuAePabaQ0UgUUElmE0yVWEKOWKg4MHIZm06oWM
vx5x6UpS8aDYZVBZfc0MscN26Hm.eakTTFvxGc+GmsE2N99UCZJ4sG7MVE8V
Xmn6iZndF.7WsB5lFLImh3IxZ1RgmECeyqDh0L4kmReWlREeFjp9GZVI96m.
GeCLvyl4LYT46UAmAM5rWljJjfTi92FWFWx7lLB8+nhhRd3TzZ8fF7C5a9fz
yxx8f9nNXFWljpEMbbot5obPkjB4yjUJUl0ycd+6dCTj+GDMVXpA
-----------end_max5_patcher-----------
</code></pre>

8.2  Contrôle par série

Cet example échantillonne une ligne horizontale du rendu de Processing ou Max pour l'afficher sur une guirlande Neopixel de 60 DEL. Il est nécessaire d'utiliser SlipMassage pour envoyer les messages assez rapidement au microcontrôleur.

Télécharger SlipMassage et les exemples ici : https://github.com/SofaPirate/SlipMassage/archive/master.zip

9.  Outils

9.1  TouchDesigner : envoi de texture par UDP

Ce code TouchDesigner subdivise une texture en plusieurs chunks qui sont par la suite envoyé par UDP. Un chunk correspond à une section de texture, c'est à dire un groupe de pixels. La texture est subdivisée en chunks parce que l'envoi de la totalité de l'image en un seul coup est trop pesant. Télécharger le code ici : TouchDesigner_texture_over_UDP.zip

9.2  Trouver le projectile le plus bas (extrait incomplet)

int iPlusBas = -1;
int posPlusBas = 100;

for ( int i = 0;  i < LENGTH ; i++ ) {
        if ( blocks[i].falling ) {
                if ( blocks[i].pos < posPlusBas ) {
                        iPlusBas = i;
                        posPlusBas = blocks[i].pos;
                }
        }

}

if ( iPlusBas > -1 ) {
        // KILLER

}