0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

零知开源——使用 GPIO 模拟时序驱动 WS2812B LED 灯带

零知实验室 来源:PCB56242069 作者:PCB56242069 2025-02-20 15:43 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

​利用零知增强版的GPIO 模拟时序

在本教程中,我们将探讨如何使用 零知增强版的 GPIO 接口来模拟 WS2812B LED 灯带的信号传输时序,从而实现对单色或多彩 LED 灯带的控制。这种技术允许我们避开专用驱动库,直接与硬件进行交互,理解并掌握 WS2812B 的通信机制。

一、工具原料

电脑、Windows系统

零知增强版开发板

Micro-usb线

WS2812RGB灯

WS2812B 是一款内含控制器芯片的全彩 LED 灯珠,每个灯珠可以独立显示红、绿、蓝三色。它通过单一数据线接收命令,实现高精度颜色控制。

二、硬件连接

零知增强版 WS2812B
5V VCC
GND GND
51 Din

1、硬件连接示意图

wKgZO2e23SWAbzzcAALcDy1Fozw229.png

2、实际效果

wKgZPGe23SaAUAZ8AARSqJQZKqs239.png

三、传输时序和颜色控制

1、信号传输时序

WS2812B 的数据传输遵循特定的时间序列:

高电平持续时间决定比特值:T1H 和 T0H 分别代表比特 1 和比特 0 的高电平持续时间。

低电平持续时间:T1L 和 T0L。

注:T1H为 800ns,T1L为 450ns 表示 1 比特。

T0H为 400ns,T0L为 850ns 表示 0 比特。

2、颜色控制

控制全局亮度和遵循WS2812B发送的时序:

通过brightness参数调节RGB灯的全局亮度

WS2812B协议发送时序为G -> R -> B

四、代码驱动

1、相关定义和初始化

​// WS2812B相关定义
#define WS2812B_PIN 51      // WS2812B数据引脚
#define NUM_LEDS 8          // 灯珠数量
#define MAX_BRIGHTNESS 0.5  // 全局亮度调节(范围:0.0 - 1.0)
 
// WS2812B控制协议时间(根据各自的时序进行修改该定义)
#define T1H 800
#define T1L 450
#define T0H 400
#define T0L 850
 
// 初始化WS2812B引脚
void setupWS2812B() {
    pinMode(WS2812B_PIN, OUTPUT);
    digitalWrite(WS2812B_PIN, LOW);
}
 
// 更精确的纳秒延时函数(这里只是示例,实际可能需要更复杂的实现)
// 假设使用了支持纳秒级延时的定时器库
// 这里暂时使用简单的微秒级延时近似
void delayNanoseconds(unsigned long ns) {
    delayMicroseconds(ns / 1000);
}

2、控制颜色和发送相关数据

​
// 发送一个比特
void WS2812B_SendBit(bool bitVal) {
    if (bitVal) {
        // 发送逻辑1
        digitalWrite(WS2812B_PIN, HIGH);
        delayNanoseconds(T1H);
        digitalWrite(WS2812B_PIN, LOW);
        delayNanoseconds(T1L);
    } else {
        // 发送逻辑0
        digitalWrite(WS2812B_PIN, HIGH);
        delayNanoseconds(T0H);
        digitalWrite(WS2812B_PIN, LOW);
        delayNanoseconds(T0L);
    }
}

// 发送一个字节
void WS2812B_SendByte(uint8_t byte) {
    for (int i = 7; i >= 0; i--) {
        WS2812B_SendBit(byte & (1 < < i));
    }
}

// 发送RGB颜色数据(带亮度调节)
void WS2812B_SendColor(uint8_t red, uint8_t green, uint8_t blue, float brightness) {
    // 应用全局亮度调节
    red = (uint8_t)(red * brightness * MAX_BRIGHTNESS);
    green = (uint8_t)(green * brightness * MAX_BRIGHTNESS);
    blue = (uint8_t)(blue * brightness * MAX_BRIGHTNESS);

    // WS2812B协议发送顺序:G - > R -> B
    WS2812B_SendByte(green);
    WS2812B_SendByte(red);
    WS2812B_SendByte(blue);
}

3、实现流水灯、呼吸灯等功能

​
// 效果:彩虹追逐
void rainbowChaseEffect(uint8_t wait) {
    for (int offset = 0; offset < 255; offset++) {
        for (int i = 0; i < NUM_LEDS; i++) {
            int hue = (i * 255 / NUM_LEDS + offset) % 255;
            uint8_t r = 0, g = 0, b = 0;
            if (hue < 85) {
                r = 255 - hue * 3;
                g = hue * 3;
                b = 0;
            } else if (hue < 170) {
                hue -= 85;
                r = 0;
                g = 255 - hue * 3;
                b = hue * 3;
            } else {
                hue -= 170;
                r = hue * 3;
                g = 0;
                b = 255 - hue * 3;
            }
            WS2812B_SendColor(r, g, b, MAX_BRIGHTNESS);
        }
        delay(wait);
    }
}

// 呼吸灯效果
void breathAndFlow(uint8_t red, uint8_t green, uint8_t blue, uint8_t steps, uint16_t period, uint8_t wait, uint8_t iterations) {
    int ledStep[NUM_LEDS]; // 为每个 LED 创建一个步骤计数器
    for (int i = 0; i < NUM_LEDS; i++) {
        ledStep[i] = 0; // 初始化每个LED的步进
    }

    uint8_t cycleCounter = 0; // 添加循环计数器

    while (cycleCounter < iterations) { // 有限循环,迭代指定次数
        for (int i = 0; i < NUM_LEDS; i++) {
            // 计算当前 LED 的亮度比例
            float brightness = (sin(ledStep[i] * (M_PI / (steps))) + 1) / 2;
            WS2812B_SendColor(red, green, blue, brightness); // 使用计算出的亮度

            // 更新 LED 的步骤计数器,模拟呼吸效果
            ledStep[i] = (ledStep[i] + 1) % (steps * 2); // 确保计数器在达到两倍步骤后重置

            // 计算每个步骤的时间间隔
            delayMicroseconds(period / steps);
        }
       
        // 在一轮呼吸之后关闭所有灯
        clearAllLeds();

        // 增加循环计数器
        cycleCounter++;

        // 根据需要添加延迟,虽然这不是必须的
        delay(wait);
    }
}

// 增加一个状态变量来记录是否有颜色覆盖
bool isCovered = false;

// 流水灯
void ShampEffect(uint8_t red, uint8_t green, uint8_t blue, uint8_t trailDecay, uint8_t wait) {
    // 特殊处理第一个灯
    WS2812B_SendColor(red, green, blue, MAX_BRIGHTNESS);
    // 从第二个灯开始的索引为1
    for (int i = 0; i < NUM_LEDS; i++) {
        for (int j = 0; j <= NUM_LEDS; j++) {
            if (i - j == 0) {
                if (!isCovered) {
                    // 如果没有被覆盖,设置为绿色
                    WS2812B_SendColor(0, 0, 0, MAX_BRIGHTNESS);
                } else {
                    WS2812B_SendColor(red, green, blue, MAX_BRIGHTNESS);
                }
            } else {
                WS2812B_SendColor(0, 0, 0, MAX_BRIGHTNESS * trailDecay / 255.0);
            }
        }
        if (i == NUM_LEDS - 1) {
            // 当到达最后一个灯时,标记为已覆盖
            isCovered = true;
        }
        delay(wait);
    }
}

4、控制灯的状态

​
// 设置特定位置灯珠颜色
void setLedColor(uint8_t pos, uint8_t red, uint8_t green, uint8_t blue, float brightness) {
    if (pos < NUM_LEDS) {
        // 只发送前面灯珠的关闭信号,直到要设置颜色的灯珠位置
        for (int i = 0; i < pos; i++) {
            WS2812B_SendColor(0, 0, 0, 0);
        }
        // 设置目标灯珠颜色
        WS2812B_SendColor(red, green, blue, brightness);
        // 发送后面灯珠的关闭信号,从目标灯珠的下一个位置开始
        for (int i = pos + 1; i < NUM_LEDS; i++) {
            WS2812B_SendColor(0, 0, 0, 0);
        }
    }
}

// 设置所有灯珠颜色
void setAllLeds(uint8_t red, uint8_t green, uint8_t blue, float brightness) {
    clearAllLeds();// 先清除所有灯珠,确保没有杂色
    for (int i = 0; i < NUM_LEDS; i++) {
        WS2812B_SendColor(red, green, blue, brightness);
    }
}

// 清除所有灯珠
void clearAllLeds() {
    for (int i = 0; i < NUM_LEDS * 3; i++) {
        WS2812B_SendByte(0);
    }
}

​

5、主循环

​
// 初始化
void setup() {
    setupWS2812B();
    clearAllLeds();  // 确保灯带初始状态关闭
}

// 主循环
void loop() {
    uint8_t Count = 0;
    //clearAllLeds();
    // 设置第六个灯珠为蓝色
    //setLedColor(5, 0, 0, 255, MAX_BRIGHTNESS);
    //delay(500);
    while(Count < 10)
    {
      ShampEffect(0, 0, random(255), 256, 200);
      Count ++;
    }
   
    //rainbowChaseEffect(1000);
    breathAndFlow(0,255,0,5,50,100,100);
}

五、成果展示

将上诉代码验证后上传到零知板,可以看到以下流水灯、呼吸灯等测试结果。

https://live.csdn.net/v/437153?spm=1001.2014.3001.5501

wKgZO2e23SaAcUrnAAEr8LvRUJ459.jpeg使用 GPIO 模拟时序驱动 WS2812B LED 灯带


审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • led
    led
    +关注

    关注

    243

    文章

    24452

    浏览量

    687824
  • 灯带
    +关注

    关注

    0

    文章

    19

    浏览量

    9532
  • 开源
    +关注

    关注

    3

    文章

    4049

    浏览量

    45596
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    基于STM32F103C8T6驱动WS2812彩灯模块点亮RGB

    一、WS2812模块简介 WS2812是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED珠相同,每个元件即为
    的头像 发表于 12-04 11:29 5907次阅读
    基于STM32F103C8T6<b class='flag-5'>驱动</b><b class='flag-5'>WS2812</b>彩灯模块点亮RGB<b class='flag-5'>灯</b>

    【瑞萨RA6E2】驱动 WS2812 实现 RGB 跑马灯效果

    WS2812_PINBSP_IO_PORT_00_PIN_01 #define WS2812_NUM3 #define SYS_CLOCK120000000 WS2812 的通信时序
    发表于 11-25 01:55

    【瑞萨RA6E2】点亮 WS2812 全彩点阵屏

    通过单总线方式控制,只需一个 IO 口,就可以点亮数千个珠。 这里使用 RA6E2 点亮 WS2812 珠,效果如下: WS2812 可以使用 IO
    发表于 11-05 08:36

    一文读懂:W55MH32 如何携手微信小程序与 OneNET,实现以太网条调色自由(软硬件开源

    本文采用W55MH32开发板搭配WS2812B条,借助MQTT协议连接OneNET云平台,并配合微信小程序,实现了以太网条的远程调色以及动态模式(如流水灯、彩虹)控制。感谢大家阅
    的头像 发表于 08-08 11:16 1242次阅读
    一文读懂:W55MH32 如何携手微信小程序与 OneNET,实现以太网<b class='flag-5'>灯</b>条调色自由(软硬件<b class='flag-5'>开源</b>)

    【RA4L1-SENSOR】点亮 WS2812 全彩点阵屏

    通过单总线方式控制,只需一个 IO 口,就可以点亮数千个珠。 这里使用 RA4L1 点亮 WS2812 珠,效果如下: WS2812 可以使用 IO
    发表于 06-09 12:48

    【RA-Eco-RA4M2开发板评测】点亮WS2812点阵屏

    通过单总线方式控制,只需一个 IO 口,就可以点亮数千个珠。 这里使用 RA4M2 点亮 WS2812 珠,效果如下: WS2812 可以使用 IO
    发表于 05-07 15:28

    WS2812B on S32K144始终闪烁白色,即使没有数据也是如此,为什么?

    我正在尝试控制WS2812B RGB LED使用型号 S32K144EVB-Q100.我的目标是发送GRB 数据使用 bit-banging onPTD0.但是,LED 始终闪烁白色 (R=255
    发表于 04-08 07:15

    CW32模块使用 WS2812彩灯

    WS2812E是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED珠相同,每个 元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大
    的头像 发表于 02-24 11:37 801次阅读
    CW32模块使用 <b class='flag-5'>WS2812</b>彩灯

    使用 GPIO 模拟时序驱动 WS2812B LED

    GPIO
    PCB56242069
    发布于 :2025年02月20日 14:47:01

    开源——使用 GPIO 模拟时序驱动 WS2812B LED

    ); breathAndFlow(0,255,0,5,50,100,100); } 五、成果展示将上诉代码验证后上传到板,可以看到以下流水灯、呼吸等测试结果。 ​ 使用 GPIO
    发表于 02-20 14:31

    开源——网页控制WS2812B

    本帖最后由 PCB56242069 于 2025-2-20 15:33 编辑 ESP Color Picker\");client.println(\"Change Color \");client.println(\"\");client.println(\"
    发表于 02-19 18:50

    开源——玩转WS2812B条模块

    WS2812RGB 通过标准开发板平台上驱动WS28
    发表于 02-19 17:25

    开源——玩转WS2812B条模块

    WS2812RGB       通过标准开发板平台上驱动
    的头像 发表于 02-19 15:09 2559次阅读
    <b class='flag-5'>零</b><b class='flag-5'>知</b><b class='flag-5'>开源</b>——玩转<b class='flag-5'>WS2812B</b><b class='flag-5'>灯</b>条模块

    标准板点亮WS2812B

    电路板
    PCB56242069
    发布于 :2025年02月19日 15:04:46

    【敏矽微ME32G070开发板免费体验】点亮WS2812B

    一、简介 板上集成了8颗RGB彩灯,但只需用到一个GPIO口,这是如何做到的呢?这节我们就点亮WS2812B展开话题。WS2812B是一个集控制电路与发光电路于一体的智能外控LED光源
    发表于 01-07 23:58