回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【雕爷学编程】Arduino动手做(138)---64位WS2812点阵屏模块4 中等

头像 驴友花雕 2023.07.13 28 2

37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞不掂的问题,希望能够抛砖引玉。

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百三十八:64位 WS2812B8*8 xRGB 5050 LED模块 ws2812s像素点阵屏

 

30.jpg

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

  实验一百三十八:64位 WS2812B8*8 xRGB 5050 LED模块 ws2812s像素点阵屏

  项目十九:骄傲2015动画,不断变化的彩虹

  实验开源代码


 

代码
/*

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

  实验一百三十八:64位 WS2812B8*8 xRGB 5050 LED模块 ws2812s像素点阵屏

 项目十九:骄傲2015动画,不断变化的彩虹

 实验接线

 Module  UNO

 VCC —— 3.3V

 GND —— GND

 DI —— D6

*/

#include "FastLED.h"

// Pride2015

// Animated, ever-changing rainbows.

// by Mark Kriegsman

#if FASTLED_VERSION < 3001000

#error "Requires FastLED 3.1 or later; check github for latest code."

#endif

#define DATA_PIN  6

//#define CLK_PIN  4

#define LED_TYPE  WS2811

#define COLOR_ORDER GRB

#define NUM_LEDS  64

#define BRIGHTNESS 22

CRGB leds[NUM_LEDS];

void setup() {

 delay(3000); // 3 second delay for recovery

  

 // tell FastLED about the LED strip configuration

 FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS)

  .setCorrection(TypicalLEDStrip)

  .setDither(BRIGHTNESS < 255);

 // set master brightness control

 FastLED.setBrightness(BRIGHTNESS);

}

void loop()

{

 pride();

 FastLED.show();  

}

// This function draws rainbows with an ever-changing,

// widely-varying set of parameters.

void pride() 

{

 static uint16_t sPseudotime = 0;

 static uint16_t sLastMillis = 0;

 static uint16_t sHue16 = 0;

 

 uint8_t sat8 = beatsin88( 87, 220, 250);

 uint8_t brightdepth = beatsin88( 341, 96, 224);

 uint16_t brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256));

 uint8_t msmultiplier = beatsin88(147, 23, 60);

 uint16_t hue16 = sHue16;//gHue * 256;

 uint16_t hueinc16 = beatsin88(113, 1, 3000);

  

 uint16_t ms = millis();

 uint16_t deltams = ms - sLastMillis ;

 sLastMillis = ms;

 sPseudotime += deltams * msmultiplier;

 sHue16 += deltams * beatsin88( 400, 5,9);

 uint16_t brightnesstheta16 = sPseudotime;

  

 for( uint16_t i = 0 ; i < NUM_LEDS; i++) {

  hue16 += hueinc16;

  uint8_t hue8 = hue16 / 256;

  brightnesstheta16 += brightnessthetainc16;

  uint16_t b16 = sin16( brightnesstheta16 ) + 32768;

  uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536;

  uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536;

  bri8 += (255 - brightdepth);

   

  CRGB newcolor = CHSV( hue8, sat8, bri8);

   

  uint16_t pixelnumber = i;

  pixelnumber = (NUM_LEDS-1) - pixelnumber;

   

  nblend( leds[pixelnumber], newcolor, 64);

 }

}

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

  实验一百三十八:64位 WS2812B8*8 xRGB 5050 LED模块 ws2812s像素点阵屏

  项目二十:TwinkleFOX:淡入淡出的闪烁“假日”灯

  实验开源代码

 


 

代码
/*

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

  实验一百三十八:64位 WS2812B8*8 xRGB 5050 LED模块 ws2812s像素点阵屏

 项目二十:TwinkleFOX:淡入淡出的闪烁“假日”灯

 实验接线

 Module  UNO

 VCC —— 3.3V

 GND —— GND

 DI —— D6

*/

#include "FastLED.h"

#define NUM_LEDS   64

#define LED_TYPE  WS2811

#define COLOR_ORDER  GRB

#define DATA_PIN    6

//#define CLK_PIN    4

#define VOLTS     12

#define MAX_MA    4000

// TwinkleFOX: Twinkling 'holiday' lights that fade in and out.

// Colors are chosen from a palette; a few palettes are provided.

//

// This December 2015 implementation improves on the December 2014 version

// in several ways:

// - smoother fading, compatible with any colors and any palettes

// - easier control of twinkle speed and twinkle density

// - supports an optional 'background color'

// - takes even less RAM: zero RAM overhead per pixel

// - illustrates a couple of interesting techniques (uh oh...)

//

// The idea behind this (new) implementation is that there's one

// basic, repeating pattern that each pixel follows like a waveform:

// The brightness rises from 0..255 and then falls back down to 0.

// The brightness at any given point in time can be determined as

// as a function of time, for example:

//  brightness = sine( time ); // a sine wave of brightness over time

//

// So the way this implementation works is that every pixel follows

// the exact same wave function over time. In this particular case,

// I chose a sawtooth triangle wave (triwave8) rather than a sine wave,

// but the idea is the same: brightness = triwave8( time ).

//

// Of course, if all the pixels used the exact same wave form, and

// if they all used the exact same 'clock' for their 'time base', all

// the pixels would brighten and dim at once -- which does not look

// like twinkling at all.

//

// So to achieve random-looking twinkling, each pixel is given a

// slightly different 'clock' signal. Some of the clocks run faster,

// some run slower, and each 'clock' also has a random offset from zero.

// The net result is that the 'clocks' for all the pixels are always out

// of sync from each other, producing a nice random distribution

// of twinkles.

//

// The 'clock speed adjustment' and 'time offset' for each pixel

// are generated randomly. One (normal) approach to implementing that

// would be to randomly generate the clock parameters for each pixel

// at startup, and store them in some arrays. However, that consumes

// a great deal of precious RAM, and it turns out to be totally

// unnessary! If the random number generate is 'seeded' with the

// same starting value every time, it will generate the same sequence

// of values every time. So the clock adjustment parameters for each

// pixel are 'stored' in a pseudo-random number generator! The PRNG

// is reset, and then the first numbers out of it are the clock

// adjustment parameters for the first pixel, the second numbers out

// of it are the parameters for the second pixel, and so on.

// In this way, we can 'store' a stable sequence of thousands of

// random clock adjustment parameters in literally two bytes of RAM.

//

// There's a little bit of fixed-point math involved in applying the

// clock speed adjustments, which are expressed in eighths. Each pixel's

// clock speed ranges from 8/8ths of the system clock (i.e. 1x) to

// 23/8ths of the system clock (i.e. nearly 3x).

//

// On a basic Arduino Uno or Leonardo, this code can twinkle 300+ pixels

// smoothly at over 50 updates per seond.

//

// -Mark Kriegsman, December 2015

CRGBArray<NUM_LEDS> leds;

// Overall twinkle speed.

// 0 (VERY slow) to 8 (VERY fast).

// 4, 5, and 6 are recommended, default is 4.

#define TWINKLE_SPEED 4

// Overall twinkle density.

// 0 (NONE lit) to 8 (ALL lit at once).

// Default is 5.

#define TWINKLE_DENSITY 5

// How often to change color palettes.

#define SECONDS_PER_PALETTE 30

// Also: toward the bottom of the file is an array

// called "ActivePaletteList" which controls which color

// palettes are used; you can add or remove color palettes

// from there freely.

// Background color for 'unlit' pixels

// Can be set to CRGB::Black if desired.

CRGB gBackgroundColor = CRGB::Black;

// Example of dim incandescent fairy light background color

// CRGB gBackgroundColor = CRGB(CRGB::FairyLight).nscale8_video(16);

// If AUTO_SELECT_BACKGROUND_COLOR is set to 1,

// then for any palette where the first two entries

// are the same, a dimmed version of that color will

// automatically be used as the background color.

#define AUTO_SELECT_BACKGROUND_COLOR 0

// If COOL_LIKE_INCANDESCENT is set to 1, colors will

// fade out slighted 'reddened', similar to how

// incandescent bulbs change color as they get dim down.

#define COOL_LIKE_INCANDESCENT 1

CRGBPalette16 gCurrentPalette;

CRGBPalette16 gTargetPalette;

void setup() {

 delay( 3000 ); //safety startup delay

 FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);

 FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS)

 .setCorrection(TypicalLEDStrip);

 FastLED.setBrightness(23);

 chooseNextColorPalette(gTargetPalette);

}

void loop()

{

 EVERY_N_SECONDS( SECONDS_PER_PALETTE ) {

  chooseNextColorPalette( gTargetPalette );

 }

 EVERY_N_MILLISECONDS( 10 ) {

  nblendPaletteTowardPalette( gCurrentPalette, gTargetPalette, 12);

 }

 drawTwinkles( leds);

 FastLED.show();

}

// This function loops over each pixel, calculates the

// adjusted 'clock' that this pixel should use, and calls

// "CalculateOneTwinkle" on each pixel. It then displays

// either the twinkle color of the background color,

// whichever is brighter.

void drawTwinkles( CRGBSet& L)

{

 // "PRNG16" is the pseudorandom number generator

 // It MUST be reset to the same starting value each time

 // this function is called, so that the sequence of 'random'

 // numbers that it generates is (paradoxically) stable.

 uint16_t PRNG16 = 11337;

 uint32_t clock32 = millis();

 // Set up the background color, "bg".

 // if AUTO_SELECT_BACKGROUND_COLOR == 1, and the first two colors of

 // the current palette are identical, then a deeply faded version of

 // that color is used for the background color

 CRGB bg;

 if ( (AUTO_SELECT_BACKGROUND_COLOR == 1) &&

    (gCurrentPalette[0] == gCurrentPalette[1] )) {

  bg = gCurrentPalette[0];

  uint8_t bglight = bg.getAverageLight();

  if ( bglight > 64) {

   bg.nscale8_video( 16); // very bright, so scale to 1/16th

  } else if ( bglight > 16) {

   bg.nscale8_video( 64); // not that bright, so scale to 1/4th

  } else {

   bg.nscale8_video( 86); // dim, scale to 1/3rd.

  }

 } else {

  bg = gBackgroundColor; // just use the explicitly defined background color

 }

 uint8_t backgroundBrightness = bg.getAverageLight();

 for ( CRGB& pixel : L) {

  PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number

  uint16_t myclockoffset16 = PRNG16; // use that number as clock offset

  PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number

  // use that number as clock speed adjustment factor (in 8ths, from 8/8ths to 23/8ths)

  uint8_t myspeedmultiplierQ5_3 = ((((PRNG16 & 0xFF) >> 4) + (PRNG16 & 0x0F)) & 0x0F) + 0x08;

  uint32_t myclock30 = (uint32_t)((clock32 * myspeedmultiplierQ5_3) >> 3) + myclockoffset16;

  uint8_t myunique8 = PRNG16 >> 8; // get 'salt' value for this pixel

  // We now have the adjusted 'clock' for this pixel, now we call

  // the function that computes what color the pixel should be based

  // on the "brightness = f( time )" idea.

  CRGB c = computeOneTwinkle( myclock30, myunique8);

  uint8_t cbright = c.getAverageLight();

  int16_t deltabright = cbright - backgroundBrightness;

  if ( deltabright >= 32 || (!bg)) {

   // If the new pixel is significantly brighter than the background color,

   // use the new color.

   pixel = c;

  } else if ( deltabright > 0 ) {

   // If the new pixel is just slightly brighter than the background color,

   // mix a blend of the new color and the background color

   pixel = blend( bg, c, deltabright * 8);

  } else {

   // if the new pixel is not at all brighter than the background color,

   // just use the background color.

   pixel = bg;

  }

 }

}

// This function takes a time in pseudo-milliseconds,

// figures out brightness = f( time ), and also hue = f( time )

// The 'low digits' of the millisecond time are used as

// input to the brightness wave function.

// The 'high digits' are used to select a color, so that the color

// does not change over the course of the fade-in, fade-out

// of one cycle of the brightness wave function.

// The 'high digits' are also used to determine whether this pixel

// should light at all during this cycle, based on the TWINKLE_DENSITY.

CRGB computeOneTwinkle( uint32_t ms, uint8_t salt)

{

 uint16_t ticks = ms >> (8 - TWINKLE_SPEED);

 uint8_t fastcycle8 = ticks;

 uint16_t slowcycle16 = (ticks >> 8) + salt;

 slowcycle16 += sin8( slowcycle16);

 slowcycle16 = (slowcycle16 * 2053) + 1384;

 uint8_t slowcycle8 = (slowcycle16 & 0xFF) + (slowcycle16 >> 8);

 uint8_t bright = 0;

 if ( ((slowcycle8 & 0x0E) / 2) < TWINKLE_DENSITY) {

  bright = attackDecayWave8( fastcycle8);

 }

 uint8_t hue = slowcycle8 - salt;

 CRGB c;

 if ( bright > 0) {

  c = ColorFromPalette( gCurrentPalette, hue, bright, NOBLEND);

  if ( COOL_LIKE_INCANDESCENT == 1 ) {

   coolLikeIncandescent( c, fastcycle8);

  }

 } else {

  c = CRGB::Black;

 }

 return c;

}

// This function is like 'triwave8', which produces a

// symmetrical up-and-down triangle sawtooth waveform, except that this

// function produces a triangle wave with a faster attack and a slower decay:

//

//   / \ 

//  /   \ 

//  /     \ 

// /       \ 

//

uint8_t attackDecayWave8( uint8_t i)

{

 if ( i < 86) {

  return i * 3;

 } else {

  i -= 86;

  return 255 - (i + (i / 2));

 }

}

// This function takes a pixel, and if its in the 'fading down'

// part of the cycle, it adjusts the color a little bit like the

// way that incandescent bulbs fade toward 'red' as they dim.

void coolLikeIncandescent( CRGB& c, uint8_t phase)

{

 if ( phase < 128) return;

 uint8_t cooling = (phase - 128) >> 4;

 c.g = qsub8( c.g, cooling);

 c.b = qsub8( c.b, cooling * 2);

}

// A mostly red palette with green accents and white trim.

// "CRGB::Gray" is used as white to keep the brightness more uniform.

const TProgmemRGBPalette16 RedGreenWhite_p FL_PROGMEM =

{ CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red,

 CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red,

 CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray,

 CRGB::Green, CRGB::Green, CRGB::Green, CRGB::Green

};

// A mostly (dark) green palette with red berries.

#define Holly_Green 0x00580c

#define Holly_Red  0xB00402

const TProgmemRGBPalette16 Holly_p FL_PROGMEM =

{ Holly_Green, Holly_Green, Holly_Green, Holly_Green,

 Holly_Green, Holly_Green, Holly_Green, Holly_Green,

 Holly_Green, Holly_Green, Holly_Green, Holly_Green,

 Holly_Green, Holly_Green, Holly_Green, Holly_Red

};

// A red and white striped palette

// "CRGB::Gray" is used as white to keep the brightness more uniform.

const TProgmemRGBPalette16 RedWhite_p FL_PROGMEM =

{ CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red,

 CRGB::Gray, CRGB::Gray, CRGB::Gray, CRGB::Gray,

 CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red,

 CRGB::Gray, CRGB::Gray, CRGB::Gray, CRGB::Gray

};

// A mostly blue palette with white accents.

// "CRGB::Gray" is used as white to keep the brightness more uniform.

const TProgmemRGBPalette16 BlueWhite_p FL_PROGMEM =

{ CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue,

 CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue,

 CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue,

 CRGB::Blue, CRGB::Gray, CRGB::Gray, CRGB::Gray

};

// A pure "fairy light" palette with some brightness variations

#define HALFFAIRY ((CRGB::FairyLight & 0xFEFEFE) / 2)

#define QUARTERFAIRY ((CRGB::FairyLight & 0xFCFCFC) / 4)

const TProgmemRGBPalette16 FairyLight_p FL_PROGMEM =

{ CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight,

 HALFFAIRY,    HALFFAIRY,    CRGB::FairyLight, CRGB::FairyLight,

 QUARTERFAIRY,   QUARTERFAIRY,   CRGB::FairyLight, CRGB::FairyLight,

 CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight

};

// A palette of soft snowflakes with the occasional bright one

const TProgmemRGBPalette16 Snow_p FL_PROGMEM =

{ 0x304048, 0x304048, 0x304048, 0x304048,

 0x304048, 0x304048, 0x304048, 0x304048,

 0x304048, 0x304048, 0x304048, 0x304048,

 0x304048, 0x304048, 0x304048, 0xE0F0FF

};

// A palette reminiscent of large 'old-school' C9-size tree lights

// in the five classic colors: red, orange, green, blue, and white.

#define C9_Red  0xB80400

#define C9_Orange 0x902C02

#define C9_Green 0x046002

#define C9_Blue  0x070758

#define C9_White 0x606820

const TProgmemRGBPalette16 RetroC9_p FL_PROGMEM =

{ C9_Red,  C9_Orange, C9_Red,  C9_Orange,

 C9_Orange, C9_Red,  C9_Orange, C9_Red,

 C9_Green, C9_Green, C9_Green, C9_Green,

 C9_Blue,  C9_Blue,  C9_Blue,

 C9_White

};

// A cold, icy pale blue palette

#define Ice_Blue1 0x0C1040

#define Ice_Blue2 0x182080

#define Ice_Blue3 0x5080C0

const TProgmemRGBPalette16 Ice_p FL_PROGMEM =

{

 Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1,

 Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1,

 Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1,

 Ice_Blue2, Ice_Blue2, Ice_Blue2, Ice_Blue3

};

// Add or remove palette names from this list to control which color

// palettes are used, and in what order.

const TProgmemRGBPalette16* ActivePaletteList[] = {

 &RetroC9_p,

 &BlueWhite_p,

 &RainbowColors_p,

 &FairyLight_p,

 &RedGreenWhite_p,

 &PartyColors_p,

 &RedWhite_p,

 &Snow_p,

 &Holly_p,

 &Ice_p

};

// Advance to the next color palette in the list (above).

void chooseNextColorPalette( CRGBPalette16& pal)

{

 const uint8_t numberOfPalettes = sizeof(ActivePaletteList) / sizeof(ActivePaletteList[0]);

 static uint8_t whichPalette = -1;

 whichPalette = addmod8( whichPalette, 1, numberOfPalettes);

 pal = *(ActivePaletteList[whichPalette]);

}

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

  实验一百三十八:64位 WS2812B8*8 xRGB 5050 LED模块 ws2812s像素点阵屏

  项目二十一:二维 XY 像素矩阵闪烁灯

  实验开源代码


 

代码
/*

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

  实验一百三十八:64位 WS2812B8*8 xRGB 5050 LED模块 ws2812s像素点阵屏

 项目二十一:二维 XY 像素矩阵闪烁灯

 实验接线

 Module  UNO

 VCC —— 3.3V

 GND —— GND

 DI —— D6

*/

#include <FastLED.h>

#define LED_PIN 6

#define COLOR_ORDER GRB

#define CHIPSET   WS2811

#define BRIGHTNESS 26

// Helper functions for an two-dimensional XY matrix of pixels.

// Simple 2-D demo code is included as well.

//

//   XY(x,y) takes x and y coordinates and returns an LED index number,

//       for use like this: leds[ XY(x,y) ] == CRGB::Red;

//       No error checking is performed on the ranges of x and y.

//

//   XYsafe(x,y) takes x and y coordinates and returns an LED index number,

//       for use like this: leds[ XYsafe(x,y) ] == CRGB::Red;

//       Error checking IS performed on the ranges of x and y, and an

//       index of "-1" is returned. Special instructions below

//       explain how to use this without having to do your own error

//       checking every time you use this function.  

//       This is a slightly more advanced technique, and 

//       it REQUIRES SPECIAL ADDITIONAL setup, described below.

// Params for width and height

const uint8_t kMatrixWidth = 16;

const uint8_t kMatrixHeight = 16;

// Param for different pixel layouts

const bool  kMatrixSerpentineLayout = true;

const bool  kMatrixVertical = false;

// Set 'kMatrixSerpentineLayout' to false if your pixels are 

// laid out all running the same way, like this:

//

//   0 > 1 > 2 > 3 > 4

//             |

//   .----<----<----<----'

//   |

//   5 > 6 > 7 > 8 > 9

//             |

//   .----<----<----<----'

//   |

//  10 > 11 > 12 > 13 > 14

//             |

//   .----<----<----<----'

//   |

//  15 > 16 > 17 > 18 > 19

//

// Set 'kMatrixSerpentineLayout' to true if your pixels are 

// laid out back-and-forth, like this:

//

//   0 > 1 > 2 > 3 > 4

//             |

//             |

//   9 < 8 < 7 < 6 < 5

//   |

//   |

//  10 > 11 > 12 > 13 > 14

//            |

//            |

//  19 < 18 < 17 < 16 < 15

//

// Bonus vocabulary word: anything that goes one way 

// in one row, and then backwards in the next row, and so on

// is call "boustrophedon", meaning "as the ox plows."

// This function will return the right 'led index number' for 

// a given set of X and Y coordinates on your matrix.  

// IT DOES NOT CHECK THE COORDINATE BOUNDARIES.  

// That's up to you. Don't pass it bogus values.

//

// Use the "XY" function like this:

//

//  for( uint8_t x = 0; x < kMatrixWidth; x++) {

//   for( uint8_t y = 0; y < kMatrixHeight; y++) {

//    

//    // Here's the x, y to 'led index' in action: 

//    leds[ XY( x, y) ] = CHSV( random8(), 255, 255);

//    

//   }

//  }

//

//

uint16_t XY( uint8_t x, uint8_t y)

{

 uint16_t i;

  

 if( kMatrixSerpentineLayout == false) {

  if (kMatrixVertical == false) {

   i = (y * kMatrixWidth) + x;

  } else {

   i = kMatrixHeight * (kMatrixWidth - (x+1))+y;

  }

 }

 if( kMatrixSerpentineLayout == true) {

  if (kMatrixVertical == false) {

   if( y & 0x01) {

    // Odd rows run backwards

    uint8_t reverseX = (kMatrixWidth - 1) - x;

    i = (y * kMatrixWidth) + reverseX;

   } else {

    // Even rows run forwards

    i = (y * kMatrixWidth) + x;

   }

  } else { // vertical positioning

   if ( x & 0x01) {

    i = kMatrixHeight * (kMatrixWidth - (x+1))+y;

   } else {

    i = kMatrixHeight * (kMatrixWidth - x) - (y+1);

   }

  }

 }

  

 return i;

}

// Once you've gotten the basics working (AND NOT UNTIL THEN!)

// here's a helpful technique that can be tricky to set up, but 

// then helps you avoid the needs for sprinkling array-bound-checking

// throughout your code.

//

// It requires a careful attention to get it set up correctly, but

// can potentially make your code smaller and faster.

//

// Suppose you have an 8 x 5 matrix of 40 LEDs. Normally, you'd

// delcare your leds array like this:

//  CRGB leds[40];

// But instead of that, declare an LED buffer with one extra pixel in

// it, "leds_plus_safety_pixel". Then declare "leds" as a pointer to

// that array, but starting with the 2nd element (id=1) of that array: 

//  CRGB leds_with_safety_pixel[41];

//  CRGB* const leds( leds_plus_safety_pixel + 1);

// Then you use the "leds" array as you normally would.

// Now "leds[0..N]" are aliases for "leds_plus_safety_pixel[1..(N+1)]",

// AND leds[-1] is now a legitimate and safe alias for leds_plus_safety_pixel[0].

// leds_plus_safety_pixel[0] aka leds[-1] is now your "safety pixel".

//

// Now instead of using the XY function above, use the one below, "XYsafe".

//

// If the X and Y values are 'in bounds', this function will return an index

// into the visible led array, same as "XY" does.

// HOWEVER -- and this is the trick -- if the X or Y values

// are out of bounds, this function will return an index of -1.

// And since leds[-1] is actually just an alias for leds_plus_safety_pixel[0],

// it's a totally safe and legal place to access. And since the 'safety pixel'

// falls 'outside' the visible part of the LED array, anything you write 

// there is hidden from view automatically.

// Thus, this line of code is totally safe, regardless of the actual size of

// your matrix:

//  leds[ XYsafe( random8(), random8() ) ] = CHSV( random8(), 255, 255);

//

// The only catch here is that while this makes it safe to read from and

// write to 'any pixel', there's really only ONE 'safety pixel'. No matter

// what out-of-bounds coordinates you write to, you'll really be writing to

// that one safety pixel. And if you try to READ from the safety pixel,

// you'll read whatever was written there last, reglardless of what coordinates

// were supplied.

#define NUM_LEDS (kMatrixWidth * kMatrixHeight)

CRGB leds_plus_safety_pixel[ NUM_LEDS + 1];

CRGB* const leds( leds_plus_safety_pixel + 1);

uint16_t XYsafe( uint8_t x, uint8_t y)

{

 if( x >= kMatrixWidth) return -1;

 if( y >= kMatrixHeight) return -1;

 return XY(x,y);

}

// Demo that USES "XY" follows code below

void loop()

{

  uint32_t ms = millis();

  int32_t yHueDelta32 = ((int32_t)cos16( ms * (27/1) ) * (350 / kMatrixWidth));

  int32_t xHueDelta32 = ((int32_t)cos16( ms * (39/1) ) * (310 / kMatrixHeight));

  DrawOneFrame( ms / 65536, yHueDelta32 / 32768, xHueDelta32 / 32768);

  if( ms < 5000 ) {

   FastLED.setBrightness( scale8( BRIGHTNESS, (ms * 256) / 5000));

  } else {

   FastLED.setBrightness(BRIGHTNESS);

  }

  FastLED.show();

}

void DrawOneFrame( uint8_t startHue8, int8_t yHueDelta8, int8_t xHueDelta8)

{

 uint8_t lineStartHue = startHue8;

 for( uint8_t y = 0; y < kMatrixHeight; y++) {

  lineStartHue += yHueDelta8;

  uint8_t pixelHue = lineStartHue;    

  for( uint8_t x = 0; x < kMatrixWidth; x++) {

   pixelHue += xHueDelta8;

   leds[ XY(x, y)] = CHSV( pixelHue, 255, 255);

  }

 }

}

void setup() {

 FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);

 FastLED.setBrightness( BRIGHTNESS );

}

Arduino实验场景图
 

22.jpg

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

  实验一百三十八:64位 WS2812B8*8 xRGB 5050 LED模块 ws2812s像素点阵屏

  项目二十二:Mark 的 xy 坐标映射代码

  实验开源代码

 


 

代码
/*

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

  实验一百三十八:64位 WS2812B8*8 xRGB 5050 LED模块 ws2812s像素点阵屏

 项目二十二:Mark 的 xy 坐标映射代码

 实验接线

 Module  UNO

 VCC —— 3.3V

 GND —— GND

 DI —— D6

*/

#include <FastLED.h>

//

// Mark's xy coordinate mapping code. See the XYMatrix for more information on it.

//

// Params for width and height

const uint8_t kMatrixWidth = 8;

const uint8_t kMatrixHeight = 8;

#define MAX_DIMENSION ((kMatrixWidth>kMatrixHeight) ? kMatrixWidth : kMatrixHeight)

#define NUM_LEDS (kMatrixWidth * kMatrixHeight)

// Param for different pixel layouts

const bool  kMatrixSerpentineLayout = true;

uint16_t XY( uint8_t x, uint8_t y)

{

 uint16_t i;

 if ( kMatrixSerpentineLayout == false) {

  i = (y * kMatrixWidth) + x;

 }

 if ( kMatrixSerpentineLayout == true) {

  if ( y & 0x01) {

   // Odd rows run backwards

   uint8_t reverseX = (kMatrixWidth - 1) - x;

   i = (y * kMatrixWidth) + reverseX;

  } else {

   // Even rows run forwards

   i = (y * kMatrixWidth) + x;

  }

 }

 return i;

}

// The leds

CRGB leds[kMatrixWidth * kMatrixHeight];

// The 32bit version of our coordinates

static uint16_t x;

static uint16_t y;

static uint16_t z;

// We're using the x/y dimensions to map to the x/y pixels on the matrix. We'll

// use the z-axis for "time". speed determines how fast time moves forward. Try

// 1 for a very slow moving effect, or 60 for something that ends up looking like

// water.

uint16_t speed = 3; // almost looks like a painting, moves very slowly

//uint16_t speed = 20; // a nice starting speed, mixes well with a scale of 100

// uint16_t speed = 33;

//uint16_t speed = 100; // wicked fast!

// Scale determines how far apart the pixels in our noise matrix are. Try

// changing these values around to see how it affects the motion of the display. The

// higher the value of scale, the more "zoomed out" the noise iwll be. A value

// of 1 will be so zoomed in, you'll mostly see solid colors.

// uint16_t scale = 1; // mostly just solid colors

// uint16_t scale = 4011; // very zoomed out and shimmery

uint16_t scale = 311;

// This is the array that we keep our computed noise values in

uint16_t noise[MAX_DIMENSION][MAX_DIMENSION];

void setup() {

 // uncomment the following lines if you want to see FPS count information

 // Serial.begin(38400);

 // Serial.println("resetting!");

 delay(3000);

 FastLED.addLeds<WS2811, 6, RGB>(leds, NUM_LEDS);

 FastLED.setBrightness(26);

 // Initialize our coordinates to some random values

 x = random16();

 y = random16();

 z = random16();

}

// Fill the x/y array of 8-bit noise values using the inoise8 function.

void fillnoise8() {

 for (int i = 0; i < MAX_DIMENSION; i++) {

  int ioffset = scale * i;

  for (int j = 0; j < MAX_DIMENSION; j++) {

   int joffset = scale * j;

   noise[i][j] = inoise8(x + ioffset, y + joffset, z);

  }

 }

 z += speed;

}

void loop() {

 static uint8_t ihue = 0;

 fillnoise8();

 for (int i = 0; i < kMatrixWidth; i++) {

  for (int j = 0; j < kMatrixHeight; j++) {

   // We use the value at the (i,j) coordinate in the noise

   // array for our brightness, and the flipped value from (j,i)

   // for our pixel's hue.

   leds[XY(i, j)] = CHSV(noise[j][i], 255, noise[i][j]);

   // You can also explore other ways to constrain the hue used, like below

   // leds[XY(i,j)] = CHSV(ihue + (noise[j][i]>>2),255,noise[i][j]);

  }

 }

 ihue += 1;

 FastLED.show();

 // delay(10);

}

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

  实验一百三十八:64位 WS2812B8*8 xRGB 5050 LED模块 ws2812s像素点阵屏

  项目二十三:随机不同像素布局的xy矩阵

  实验开源代码

 


 

代码
/*

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

  实验一百三十八:64位 WS2812B8*8 xRGB 5050 LED模块 ws2812s像素点阵屏

 项目二十三:随机不同像素布局的xy矩阵

 实验接线

 Module  UNO

 VCC —— 3.3V

 GND —— GND

 DI —— D6

*/

#include <FastLED.h>

// Params for width and height

const uint8_t kMatrixWidth = 8;

const uint8_t kMatrixHeight = 8;

#define NUM_LEDS (kMatrixWidth * kMatrixHeight)

// Param for different pixel layouts

#define kMatrixSerpentineLayout true

// led array

CRGB leds[kMatrixWidth * kMatrixHeight];

// x,y, & time values

uint32_t x,y,v_time,hue_time,hxy;

// Play with the values of the variables below and see what kinds of effects they

// have! More octaves will make things slower.

// how many octaves to use for the brightness and hue functions

uint8_t octaves=1;

uint8_t hue_octaves=3;

// the 'distance' between points on the x and y axis

int xscale=57771;

int yscale=57771;

// the 'distance' between x/y points for the hue noise

int hue_scale=1;

// how fast we move through time & hue noise

int time_speed=1111;

int hue_speed=31;

// adjust these values to move along the x or y axis between frames

int x_speed=331;

int y_speed=1111;

void loop() {

 // fill the led array 2/16-bit noise values

 fill_2dnoise16(leds, kMatrixWidth, kMatrixHeight, kMatrixSerpentineLayout,

        octaves,x,xscale,y,yscale,v_time,

        hue_octaves,hxy,hue_scale,hxy,hue_scale,hue_time, false);

 FastLED.show();

 // adjust the intra-frame time values

 x += x_speed;

 y += y_speed;

 v_time += time_speed;

 hue_time += hue_speed;

 // delay(50);

}

void setup() {

 // initialize the x/y and time values

 random16_set_seed(8934);

 random16_add_entropy(analogRead(3));

 Serial.begin(57600);

 Serial.println("resetting!");

 delay(3000);

 FastLED.addLeds<WS2811,6,GRB>(leds,NUM_LEDS);

 FastLED.setBrightness(36);

 hxy = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();

 x = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();

 y = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();

 v_time = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();

 hue_time = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();

}

评论

user-avatar
  • hacker_

    hacker_2023.08.16

    666

    0
    • 匿名

      匿名

      该评论已删除

      1
      • 驴友花雕

        驴友花雕2023.07.13

        谢谢老师的鼓励!

    icon 他的勋章
      展开更多