# Adafruit_NeoPixel 模块 API 手册

## 1. 概述

Adafruit_NeoPixel 是一个用于驱动 NeoPixel 可寻址 LED 灯带的 Arduino 库。它支持多种 NeoPixel 兼容设备（WS2811、WS2812、WS2812B、SK6812 等），提供了简单易用的接口来控制 LED 的颜色和亮度，K230已经支持了该库。

## 2. API 介绍

### 2.1 构造函数

```cpp
Adafruit_NeoPixel(uint16_t n, int16_t pin = 6, neoPixelType type = NEO_GRB + NEO_KHZ800)
```

创建一个新的 NeoPixel 对象。

**参数**

- `n`: LED 数量
- `pin`: 数据引脚（默认为 6）
- `type`: 像素类型，由颜色顺序和频率常数相加组成（如 `NEO_GRB + NEO_KHZ800`）

**示例**

```cpp
Adafruit_NeoPixel strip(60, 6, NEO_GRB + NEO_KHZ800); // 60个LED，引脚6，GRB顺序，800KHz
```

```cpp
Adafruit_NeoPixel()
```

创建一个空的 NeoPixel 对象，需要后续调用 `updateLength()`, `updateType()` 和 `setPin()` 进行配置。

### 2.2 析构函数

```cpp
~Adafruit_NeoPixel()
```

销毁 NeoPixel 对象，释放资源并将数据引脚设置为输入模式。

### 2.3 `begin` 方法

```cpp
bool begin(void)
```

初始化 NeoPixel 引脚为输出模式。

**返回值**

- `true`: 初始化成功
- `false`: 初始化失败（通常是因为引脚号无效）

### 2.4 `show` 方法

```cpp
void show(void)
```

将 RAM 中的像素数据传输到 NeoPixel LED。此函数会暂时禁用中断以确保精确的时序。

**注意**

- 调用此函数会暂时影响 `millis()` 和 `micros()` 的准确性
- 每个 RGB 像素约需要 30 微秒，RGBW 像素约需要 40 微秒

### 2.5 `setPin` 方法

```cpp
void setPin(int16_t p)
```

设置或更改 NeoPixel 数据引脚。

**参数**

- `p`: Arduino 引脚编号（-1 表示无引脚）

### 2.6 `setPixelColor` 方法（RGB）

```cpp
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
```

使用单独的红、绿、蓝分量设置像素颜色。

**参数**

- `n`: 像素索引（从 0 开始）
- `r`: 红色亮度（0-255）
- `g`: 绿色亮度（0-255）
- `b`: 蓝色亮度（0-255）

### 2.7 `setPixelColor` 方法（RGBW）

```cpp
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w)
```

使用单独的红、绿、蓝、白分量设置像素颜色（仅适用于 RGBW NeoPixel）。

**参数**

- `n`: 像素索引（从 0 开始）
- `r`: 红色亮度（0-255）
- `g`: 绿色亮度（0-255）
- `b`: 蓝色亮度（0-255）
- `w`: 白色亮度（0-255）

### 2.8 `setPixelColor` 方法（32位颜色值）

```cpp
void setPixelColor(uint16_t n, uint32_t c)
```

使用 32 位打包的 RGB 或 RGBW 值设置像素颜色。

**参数**

- `n`: 像素索引（从 0 开始）
- `c`: 32 位颜色值（最高字节为白色（RGBW）或忽略（RGB），接下来是红色、绿色，最低字节是蓝色）

### 2.9 `fill` 方法

```cpp
void fill(uint32_t c = 0, uint16_t first = 0, uint16_t count = 0)
```

用颜色填充全部或部分 NeoPixel 灯带。

**参数**

- `c`: 32 位颜色值（默认为 0，关闭）
- `first`: 要填充的第一个像素的索引（默认为 0）
- `count`: 要填充的像素数（0 或未指定将填充到灯带末端）

### 2.10 `setBrightness` 方法

```cpp
void setBrightness(uint8_t b)
```

设置输出亮度。不会立即影响当前显示的 LED，下次调用 `show()` 时才会生效。

**参数**

- `b`: 亮度设置（0=最小/关闭，255=最亮）

**注意**

- 此函数设计为一次性在 `setup()` 中使用，而不是作为动画效果
- 更改亮度是"有损"操作，写入像素的值可能与读回的值不同

### 2.11 `clear` 方法

```cpp
void clear(void)
```

将整个 NeoPixel 灯带填充为 0/黑色/关闭。

### 2.12 `updateLength` 方法

```cpp
void updateLength(uint16_t n)
```

更改先前声明的 Adafruit_NeoPixel 灯带对象的长度。

**参数**

- `n`: 灯带的新长度（像素数）

**注意**

- 此函数已弃用，新项目应使用构造函数

### 2.13 `updateType` 方法

```cpp
void updateType(neoPixelType t)
```

更改先前声明的 Adafruit_NeoPixel 灯带对象的像素格式。

**参数**

- `t`: 像素类型

**注意**

- 此函数已弃用，新项目应使用构造函数

### 2.14 `canShow` 方法

```cpp
bool canShow(void)
```

检查调用 `show()` 是否会立即开始发送数据或需要"阻塞"一段时间。

**返回值**

- `true`: `show()` 将立即开始发送
- `false`: `show()` 将阻塞（表示有一些空闲时间可用）

### 2.15 `getPixels` 方法

```cpp
uint8_t *getPixels(void) const
```

获取指向 NeoPixel 数据缓冲区的直接指针。

**返回值**

- 指向 NeoPixel 缓冲区的指针（uint8_t* 数组）

**注意**

- 这是用于高性能应用程序的，在每像素调用 `setPixelColor()` 太慢的情况下使用
- 没有边界检查，写入缓冲区末尾可能导致问题

### 2.16 `getBrightness` 方法

```cpp
uint8_t getBrightness(void) const
```

获取灯带的最后设置的亮度值。

**返回值**

- 亮度值：0 = 最小（关闭），255 = 最大

### 2.17 `getPin` 方法

```cpp
int16_t getPin(void) const
```

获取用于 NeoPixel 数据输出的引脚编号。

**返回值**

- Arduino 引脚编号（-1 如果未设置）

### 2.18 `numPixels` 方法

```cpp
uint16_t numPixels(void) const
```

返回 Adafruit_NeoPixel 灯带对象中的像素数。

**返回值**

- 像素计数（0 如果未设置）

### 2.19 `getPixelColor` 方法

```cpp
uint32_t getPixelColor(uint16_t n) const
```

查询先前设置的像素的颜色。

**参数**

- `n`: 要读取的像素索引（0 = 第一个）

**返回值**

- 打包的 32 位 RGB 或 WRGB 值

### 2.20 `rainbow` 方法

```cpp
void rainbow(uint16_t first_hue = 0, int8_t reps = 1, uint8_t saturation = 255, uint8_t brightness = 255, bool gammify = true)
```

用一种或多种色调循环填充 NeoPixel 灯带。

**参数**

- `first_hue`: 第一个像素的色调（0-65535）
- `reps`: 灯带长度上的色轮循环数（默认为 1）
- `saturation`: 饱和度（0-255，默认为 255）
- `brightness`: 亮度/值（0-255，默认为 255）
- `gammify`: 如果为 true（默认），应用伽马校正以获得更好的外观

### 2.21 静态颜色转换方法

#### `Color` (RGB)

```cpp
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b)
```

将单独的红、绿、蓝值转换为单个"打包"的 32 位 RGB 颜色。

**参数**

- `r`: 红色亮度（0-255）
- `g`: 绿色亮度（0-255）
- `b`: 蓝色亮度（0-255）

**返回值**

- 32 位打包的 RGB 值

#### `Color` (RGBW)

```cpp
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w)
```

将单独的红、绿、蓝、白值转换为单个"打包"的 32 位 WRGB 颜色。

**参数**

- `r`: 红色亮度（0-255）
- `g`: 绿色亮度（0-255）
- `b`: 蓝色亮度（0-255）
- `w`: 白色亮度（0-255）

**返回值**

- 32 位打包的 WRGB 值

#### `ColorHSV`

```cpp
static uint32_t ColorHSV(uint16_t hue, uint8_t sat = 255, uint8_t val = 255)
```

将色调、饱和度和值转换为打包的 32 位 RGB 颜色。

**参数**

- `hue`: 色调值（0-65535）
- `sat`: 饱和度（0-255，默认为 255）
- `val`: 值/亮度（0-255，默认为 255）

**返回值**

- 打包的 32 位 RGB 值

#### `gamma8`

```cpp
static uint8_t gamma8(uint8_t x)
```

8 位伽马校正函数，用于基本像素亮度调整。

**参数**

- `x`: 输入亮度（0-255）

**返回值**

- 伽马调整后的亮度（0-255）

#### `gamma32`

```cpp
static uint32_t gamma32(uint32_t x)
```

32 位打包 RGB 或 WRGB 颜色的伽马校正函数。

**参数**

- `x`: 32 位打包的 RGB 或 WRGB 颜色

**返回值**

- 伽马调整后的打包颜色

#### `sine8`

```cpp
static uint8_t sine8(uint8_t x)
```

8 位整数正弦波函数。

**参数**

- `x`: 输入角度（0-255）

**返回值**

- 正弦结果（0-255）

#### `str2order`

```cpp
static neoPixelType str2order(const char *v)
```

从字符串（如 "BGR"）转换像素颜色顺序为 NeoPixel 颜色顺序常量。

**参数**

- `v`: 输入字符串

**返回值**

- NeoPixel 颜色顺序常量

## 3. 使用说明

### 3.1 颜色顺序常量

库定义了多种颜色顺序常量，用于指定像素数据格式：

**RGB 类型（3字节/像素）**

- `NEO_RGB` - 传输顺序：红、绿、蓝
- `NEO_RBG` - 传输顺序：红、蓝、绿
- `NEO_GRB` - 传输顺序：绿、红、蓝（最常见）
- `NEO_GBR` - 传输顺序：绿、蓝、红
- `NEO_BRG` - 传输顺序：蓝、红、绿
- `NEO_BGR` - 传输顺序：蓝、绿、红

**RGBW 类型（4字节/像素）**

- `NEO_WRGB`, `NEO_WRBG`, `NEO_WGRB` 等 - 各种白、红、绿、蓝的组合

**频率常量**

- `NEO_KHZ800` - 800 KHz 数据传输（大多数 NeoPixel 的默认值）
- `NEO_KHZ400` - 400 KHz 数据传输（用于较旧的设备）

### 3.2 基本使用流程

1. 包含头文件并创建 NeoPixel 对象
2. 在 `setup()` 中调用 `begin()`
3. 使用 `setPixelColor()` 设置像素颜色
4. 调用 `show()` 更新 LED 显示

## 4. 示例程序

```cpp
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

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

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 45

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 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)


// setup() function -- runs once at startup --------------------------------

void setup() {
  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
  // Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}


// loop() function -- runs repeatedly as long as board is on ---------------

void loop() {
  // Fill along the length of the strip in various colors...
  colorWipe(strip.Color(255,   0,   0), 50); // Red
  colorWipe(strip.Color(  0, 255,   0), 50); // Green
  colorWipe(strip.Color(  0,   0, 255), 50); // Blue

  // Do a theater marquee effect in various colors...
  theaterChase(strip.Color(127, 127, 127), 50); // White, half brightness
  theaterChase(strip.Color(127,   0,   0), 50); // Red, half brightness
  theaterChase(strip.Color(  0,   0, 127), 50); // Blue, half brightness

  rainbow(10);             // Flowing rainbow cycle along the whole strip
  theaterChaseRainbow(50); // Rainbow-enhanced theaterChase variant
}


// Some functions of our own for creating animated effects -----------------

// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
    strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}

// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
  for(int a=0; a<10; a++) {  // Repeat 10 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in steps of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show(); // Update strip with new contents
      delay(wait);  // Pause for a moment
    }
  }
}

// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
  // Hue of first pixel runs 5 complete loops through the color wheel.
  // Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
  // means we'll make 5*65536/256 = 1280 passes through this loop:
  for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
    // strip.rainbow() can take a single argument (first pixel hue) or
    // optionally a few extras: number of rainbow repetitions (default 1),
    // saturation and value (brightness) (both 0-255, similar to the
    // ColorHSV() function, default 255), and a true/false flag for whether
    // to apply gamma correction to provide 'truer' colors (default true).
    strip.rainbow(firstPixelHue);
    // Above line is equivalent to:
    // strip.rainbow(firstPixelHue, 1, 255, 255, true);
    strip.show(); // Update strip with new contents
    delay(wait);  // Pause for a moment
  }
}

// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
  int firstPixelHue = 0;     // First pixel starts at red (hue 0)
  for(int a=0; a<30; a++) {  // Repeat 30 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in increments of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        // hue of pixel 'c' is offset by an amount to make one full
        // revolution of the color wheel (range 65536) along the length
        // of the strip (strip.numPixels() steps):
        int      hue   = firstPixelHue + c * 65536L / strip.numPixels();
        uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show();                // Update strip with new contents
      delay(wait);                 // Pause for a moment
      firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
    }
  }
}
```
