WS2812B智能外控集成LED灯驱动编程

1、WS2812B应用场景

        WS2812B是一个集控制电路与发光电路于一体的智能外控LED光源,同时也是一款高性能的LED驱动器,具有高效率、低功耗、稳定性能等特点,广泛应用于各种照明和显示设备。例如下面列举出来的是一些可能的、常见的应用场景:

①、LED灯带和LED模块:用来制作全彩色LED灯带和LED模块,实现各种炫彩的灯光效果,如游戏键盘。

②、室内外照明:因其高效率、低功耗和稳定性能,非常适合用于室内外照明设备,如路灯、景观灯、室内照明灯具等。

③、商业照明和广告牌:全彩色显示和易于控制的特性使其成为商业照明和广告牌的理想选择。

④、艺术装置和舞台表演:通过编程创造出的各种独特的灯光效果,为舞台表演增添更多的视觉冲击力。

⑤、智能家居控制系统:与智能家居控制系统集成,实现灯光的智能控制。

WS2812B循环闪烁控制效果图

2、WS2812B驱动控制原理

①、模块接线说明   

        LED具有低电压驱动、环保节能、亮度高、散射角度大、一致性好超、低功率及超长寿命等优点。将控制电路集成于LED上面,电路变得更加简单,体积小,安装更加简便。

如下图所示,WS2812B灯珠模块一共有4根管脚:

VDD:电源供电管脚

VSS:信号接地和电源接地引脚

DOUT:控制数据信号输出引脚

DIN:控制数据信号输入引脚

        

                      WS2812B单灯珠模块示意图

        在实际的项目工程开发中,往往并不是一个WS2812B灯珠进行控制,因此需要掌握了解多灯珠控制接线的方法。

        如下图所示可知,如要实现多灯珠控制,需要采用串联的方式将各个独立的灯珠模块进行联通。即上一个灯珠的DOUT端引脚接入下一个灯珠的DIN引脚。最后一个灯珠的DOUT引脚不接,而第一个灯珠的DIN引脚接到控制器的数据输出控制端。

WS2812B多灯珠串联接线示意图

②、通信编码数据解析

        WS2812B的数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。像素点采用自动整形转发技术,使得该像素点的级联个数不受信号传送的限制,仅受限信号传输速度要求。

        WS2812B的一个数据帧结构为24bit,即3个字节,其中 0~7 bit为蓝色像素字节,8~15bit为红色像素字节,16~23bit为绿色像素字节。

        数据发送时,从高位到低位传输到WS2812B灯珠模块中。通信数据是MSB的格式,高位先发原则。

如果要使WS2812B显示如下图所示的颜色数据,那么需要将发送的数据按照进行组合。

//高位先发原则,按照GRB的顺序组合发送数据
//在程序中可以采用如下两种常见的数据定义形式
//方式1
unsigned char color[3] = {155, 23, 186}; //GRB
//方式2
typedef struct ws2812b{
    unsigned char green;    //G
    unsigned char red;      //R
    unsigned char blue;     //B
}ws2812b_t;

ws2812b_t data = {0};
data.green = 155;
data.red   = 23;
data.blue  = 186;

从Windows的画图软件中随意选择一种颜色,然后查看其RGB颜色编码方式,后续的程序代码中,可以直接使用这些像素数据。

        如下图所示为多颗WS2812B串联灯珠通信的抽象数据传输图,可见数据全部从D1号灯珠的DIN引脚输入,然后第一颗灯珠只提取第一个24位(3个字节)的数据,其余数据全部通过D1号灯珠的DO引脚输出到下一颗灯珠,每颗灯珠都只提取接收到的前3个字节数据后,发送到下一个灯珠,以此类推。

如下图所示位WS2812B官方手册对于0码和1码的说明

0码:高电平时间较短(约350ns),低电平时间较长(约850ns)

1码:高电平时间较长(约850ns),低电平时间较短(约350ns)

从时序图可以看到,WS2812B通信的0码和1码采用周期相同,占空比不同的方波来表示的。

3、WS2812B通信驱动编程

①、通信编程思路

(1)、GPIO引脚初始化

(2)、实现ws2812b的数据电平0

(3)、实现ws2812b的数据电平1

(4)、实现ws2812b的复位信号

(5)、实现写单字节数据(8位)

(6)、实现写3个字节数据(24位RGB)

上面的步骤(2)、(3)、(4)中,需要严格控制延时的时间!!!

        上面部分的知识体系是通用的,适用于WS2812B在各种平台上进行开发。当前手上只有一块ESP32S3,所以下面的程序代码是使用这块开发板进行开发适配的,如果需要在其它平台(GD32、STM32、CH32、CW32或嵌入式Linux等)上实现,那么可以根据上面的驱动编程思路进行简单的编写即可实现。

        根据开发板WS2812B模块部分的原理图可知,WS2812B的数据输入DIN引脚为GPIO48。这里的GPIO输出引脚选择配置,需要根据各自的开发板实际情况进行设置。      

        下面所示的代码使用的是ESP-IDF v5.1框架平台开发的。

②、main.c

#include <stdio.h>
#include <unistd.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "driver/rmt_tx.h"
#include "ws2812b.h"


int app_main(void)
{
    printf("ws2812B RMT Display starting...\n");

    ws2812b_rmt_init();
    ws2812b_t color = {0};

    while(1)
    {
        color.green = 255;
        color.red = 25;
        color.blue = 250;

        ws2812b_rmt_show_color(color);
        vTaskDelay(500/portTICK_PERIOD_MS);
        color.green = 24;
        color.red = 255;
        color.blue = 234;
        ws2812b_rmt_show_color(color);
        vTaskDelay(500/portTICK_PERIOD_MS);

        color.green = 212;
        color.red = 255;
        color.blue = 42;
        ws2812b_rmt_show_color(color);
        vTaskDelay(500/portTICK_PERIOD_MS);
    }

    return 0;
}

③、ws2812b.h

#ifndef __WS2812B_H
#define __WS2812B_H

#include "stdio.h"
#include "unistd.h"
#include "driver/gpio.h"
#include "driver/rmt_tx.h"


typedef struct ws2812b{
    unsigned char green;    //G
    unsigned char red;      //R
    unsigned char blue;     //B
}ws2812b_t;

extern rmt_channel_handle_t ws2812b_tx;
extern rmt_tx_channel_config_t ws2812b_tx_config;
extern rmt_encoder_handle_t ws2812b_encode;
extern rmt_bytes_encoder_config_t ws2812b_byte_encode;
extern rmt_transmit_config_t trans_config;

int ws2812b_rmt_init(void);
void ws2812b_rmt_show_color(ws2812b_t color);

#endif

④、ws2812b.c

#include "ws2812b.h"


rmt_channel_handle_t ws2812b_tx = NULL;
rmt_tx_channel_config_t ws2812b_tx_config = {0};
rmt_encoder_handle_t ws2812b_encode = NULL;
rmt_bytes_encoder_config_t ws2812b_byte_encode = {0};
rmt_transmit_config_t trans_config = {0};

/**
  * @brief WS2812B RMT控制初始化
  * @param None
  * @retval None
  */
int ws2812b_rmt_init(void)
{
    gpio_config_t gpio48;
    gpio48.intr_type = GPIO_INTR_DISABLE;
    gpio48.mode = GPIO_MODE_OUTPUT;
    gpio48.pin_bit_mask = (1ULL << GPIO_NUM_48); // 设置 GPIO48
    gpio48.pull_down_en = GPIO_PULLDOWN_ENABLE;
    gpio48.pull_up_en = GPIO_PULLUP_DISABLE;

    if(gpio_config(&gpio48) != ESP_OK)
    {
        printf("配置GPIO引脚失败\n");
        return -1;
    }

    gpio_set_level(GPIO_NUM_48, 0);

    
    ws2812b_tx_config.clk_src = RMT_CLK_SRC_DEFAULT; 
    ws2812b_tx_config.gpio_num = GPIO_NUM_48;
    ws2812b_tx_config.mem_block_symbols = 64;
    ws2812b_tx_config.resolution_hz = 10 * 1000 * 1000;
    ws2812b_tx_config.trans_queue_depth = 4;
    ws2812b_tx_config.flags.invert_out = false;
    ws2812b_tx_config.flags.with_dma = false;
    
    ESP_ERROR_CHECK(rmt_new_tx_channel(&ws2812b_tx_config, &ws2812b_tx));
    


    //rmt_encoder_handle_t ws2812b_encode = NULL;

    ws2812b_byte_encode.bit0.level0 = 1;
    ws2812b_byte_encode.bit0.duration0 = 3; //0.3us
    ws2812b_byte_encode.bit0.level1 = 0;
    ws2812b_byte_encode.bit0.duration1 = 9; //0.9us

    ws2812b_byte_encode.bit1.level0 = 1;
    ws2812b_byte_encode.bit1.duration0 = 9; //0.9us
    ws2812b_byte_encode.bit1.level1 = 0;
    ws2812b_byte_encode.bit1.duration1 = 3; //0.3us
    
    ws2812b_byte_encode.flags.msb_first = 1;   //大端先发
    
    rmt_new_bytes_encoder(&ws2812b_byte_encode, &ws2812b_encode); 

    ESP_ERROR_CHECK(rmt_enable(ws2812b_tx));

    trans_config.loop_count = 0;  //不循环发送

    

    ws2812b_t color;
    color.green = 155;
    color.red = 23;
    color.blue = 186;
    rmt_transmit(ws2812b_tx, ws2812b_encode, &color, sizeof(color), &trans_config);
    rmt_tx_wait_all_done(ws2812b_tx, 0xFF);
    

    return 0;

}

/**
  * @brief WS2812B RMT控制显示颜色
  * @param color :颜色RGB数据
  * @retval None
  */
void ws2812b_rmt_show_color(ws2812b_t color)
{
    extern rmt_channel_handle_t ws2812b_tx;
    extern rmt_encoder_handle_t ws2812b_encode;
    extern rmt_transmit_config_t trans_config;

    rmt_transmit(ws2812b_tx, ws2812b_encode, &color, sizeof(color), &trans_config);
    rmt_tx_wait_all_done(ws2812b_tx, 0xFF);
    gpio_set_level(GPIO_NUM_48, 0);
}

  • 30
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ws2812b智能led是一种非常常见的LED珠,具有高度集成的特点,可以实现各种颜色的光效果。下面具体介绍四种高效控制方法,并附上代码实现。 第一种方法是使用Arduino开发板,结合FastLED库来控制ws2812b智能led。首先需要安装FastLED库,然后初始化LED的数量和引脚,接下来就可以使用FastLED提供的API来设置各种光效果了。以下是示例代码: ``` #include <FastLED.h> #define LED_PIN 6 #define LED_COUNT 10 CRGB leds[LED_COUNT]; void setup() { FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, LED_COUNT); } void loop() { // 设置光效果 fill_solid(leds, LED_COUNT, CRGB::Red); FastLED.show(); delay(500); fill_solid(leds, LED_COUNT, CRGB::Green); FastLED.show(); delay(500); fill_solid(leds, LED_COUNT, CRGB::Blue); FastLED.show(); delay(500); } ``` 第二种方法是使用Raspberry Pi单片机,结合rpi_ws281x库来控制ws2812b智能led。首先需要安装rpi_ws281x库,然后初始化LED的数量、GPIOPin等信息,接下来就可以使用rpi_ws281x提供的API来设置各种光效果。以下是示例代码: ``` import time from rpi_ws281x import * LED_PIN = 18 LED_COUNT = 10 strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, 800000, 10, False, 255, 0, ws.WS2811_STRIP_GRB) strip.begin() def set_color(color): for i in range(LED_COUNT): strip.setPixelColor(i, color) strip.show() while True: # 设置光效果 set_color(Color(255, 0, 0)) # 红色 time.sleep(0.5) set_color(Color(0, 255, 0)) # 绿色 time.sleep(0.5) set_color(Color(0, 0, 255)) # 蓝色 time.sleep(0.5) ``` 第三种方法是使用ESP8266或ESP32单片机,结合FastLED库来控制ws2812b智能led。首先需要安装FastLED库,然后初始化LED的数量和引脚,接下来就可以使用FastLED提供的API来设置各种光效果。以下是示例代码: ``` #include <FastLED.h> #define LED_PIN 2 #define LED_COUNT 10 CRGB leds[LED_COUNT]; void setup() { FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, LED_COUNT); } void loop() { // 设置光效果 fill_solid(leds, LED_COUNT, CRGB::Red); FastLED.show(); delay(500); fill_solid(leds, LED_COUNT, CRGB::Green); FastLED.show(); delay(500); fill_solid(leds, LED_COUNT, CRGB::Blue); FastLED.show(); delay(500); } ``` 第四种方法是使用树莓派通过物联网通信协议,远程控制ws2812b智能led。通过树莓派连接网络,可以使用MQTT或者HTTP等通信协议与其他设备进行通信。以下是示例代码: ``` import paho.mqtt.client as mqtt from neopixel import * LED_PIN = 18 LED_COUNT = 10 strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, 800000, 10, False, 255, 0, ws.WS2811_STRIP_GRB) strip.begin() def set_color(r, g, b): for i in range(LED_COUNT): strip.setPixelColor(i, Color(g, r, b)) strip.show() def on_connect(client, userdata, flags, rc): print("Connected with result code " + str(rc)) client.subscribe("led/control") def on_message(client, userdata, msg): print(msg.topic + " " + str(msg.payload)) payload = str(msg.payload)[2:-1].split(',') set_color(int(payload[0]), int(payload[1]), int(payload[2])) client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect("localhost", 1883, 60) client.loop_forever() ``` 以上是四种高效控制ws2812b智能led的方法,分别使用Arduino、Raspberry Pi、ESP8266/ESP32和树莓派通过物联网通信实现。具体的控制方法可以根据需求进行选择和适配。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值