【小安派试玩】WS2812B RGB彩灯

[复制链接]
查看1803 | 回复10 | 2023-9-2 22:40:29 | 显示全部楼层 |阅读模式
简介:WS2812B 是一款RGB LED驱动集成电路,常用于LED灯带、装饰灯和数字屏幕等。它包含了控制芯片、红、绿、蓝三种不同颜色的LED以及一个电源引脚。WS2812B 的最大特点是其数字信号控制方式,只需通过单根总线即可控制多个WS2812B LED。WS2812B的通信协议使用的是时间间隔调制(Time-Division Multiplexing, TDM)的方法,即为每一个数据位(bit)分配一个固定的时间,通过高低电平的变化来表示不同的数据。例如,当数据位为1时,投射出的波形为低电平持续 0.35us 后切换到高电平,再持续 0.8us,当数据位为0时,投射出的波形为低电平持续 0.8us 后切换到高电平,再持续 0.45us。通过合理的时间间隔控制,可以让WS2812B正确地解析和显示码流数据,它相较于其他LED驱动芯片的优点在于内部集成控制器、单根总线多个LED控制、高亮度丰富颜色显示和多种灯光效果实现,然而,它的缺点是对驱动电压范围的要求较严格、功率消耗较大,需要注意散热和电源供应,并且对通信协议有一定了解要求。
中文数据手册:点我点我



大家好,最近楼楼研究了如何用小安派驱动ws2812这个灯珠,不得不说一下,点灯是楼楼的众多爱好之一,在楼楼的不懈努力之下,终于使用小安派的io点亮了灯珠,分享出来供大家参考


实物展示:

· 显示图片(有没有很眼熟/滑稽)


m2.jpg




· 显示文字(小安派yyds/超级大声)


v1.gif



· 一些灯效:


v5.gif




v2.gif





v4.gif





v3.gif

相信大家对于点灯这件事应该已经轻车熟路了,闭着眼都会,楼楼也不啰嗦啦,直接上代码!


代码调用流程:
· 初始化: WS2812_init(uint8_t pin, int num_leds, uint8_t brightness, uint8_t mode) ; // 引脚号,灯珠数,亮度,发送顺序(1= rgb,2 = gbr)
· 设置颜色: setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b); // 第几颗灯珠,rgb颜色
· 刷新点亮: pixel_show();
这三步完成烧录后不出意外就可以点亮灯珠


代码:

ws2812.h,新建一个ws2812.h的文件把代码复制进去就可以啦
  1. /*WS2812RGB彩灯驱动*/

  2. #ifndef _WS2812_H_
  3. #define _WS2812_H_

  4. #include "bflb_mtimer.h"
  5. #include "bflb_gpio.h"

  6. typedef union {
  7.     struct {
  8.         uint8_t g;
  9.         uint8_t r;
  10.         uint8_t b;
  11.     } simple;
  12.     uint8_t grb[3];
  13. } color_t;

  14. typedef struct _rgb_strip_t {
  15.     int pin_num;
  16.     int num_leds;
  17.     color_t *leds;
  18. } rgb_strip_t;

  19. rgb_strip_t strip;

  20. struct bflb_device_s *gpio;
  21. uint8_t _pin,_brightness,_mode;



  22. // 设置亮度.
  23. void setBrightness(uint8_t brg) {
  24.     _brightness = brg;
  25. }


  26. // 引脚初始化.
  27. /**
  28. * @brief
  29. *
  30. * @param pin  引脚号
  31. * @param num_leds  灯珠数量
  32. * @param brightness  亮度
  33. * @param mode rgb还是gbr顺序发送,1是RGB,2是GBR
  34. */
  35. void WS2812_init(uint8_t pin, int num_leds, uint8_t brightness, uint8_t mode) {

  36.         if(mode==1)_mode=1;
  37.         else if (mode == 2)_mode=2;
  38.         else return;

  39.     _pin = pin;
  40.     strip.num_leds = num_leds;
  41.         strip.pin_num = _pin;
  42.         _brightness = brightness;
  43.         strip.leds = (color_t*)malloc(sizeof(color_t) * num_leds);
  44.     for (int i = 0; i < num_leds; i++) {
  45.         strip.leds[i].simple.g = 0;
  46.         strip.leds[i].simple.r = 0;
  47.         strip.leds[i].simple.b = 0;
  48.     }

  49.     gpio = bflb_device_get_by_name("gpio");
  50.     bflb_gpio_init(gpio, pin, GPIO_OUTPUT|GPIO_FLOAT);
  51.     // bflb_gpio_reset(gpio, pin);
  52.    
  53.    
  54. }


  55. // RGB发送1码.
  56. void sendOne(uint8_t GPIO_Pin) {
  57.     bflb_gpio_set(gpio, _pin);
  58.     //延时850ns
  59.     for (volatile int i = 0; i < 30; i++);
  60.     bflb_gpio_reset(gpio, _pin);
  61.     //延时400ns
  62.     for (volatile int i = 0; i < 20; i++);
  63. }

  64. // RGB发送0码.
  65. void sendZero(uint8_t GPIO_Pin) {
  66.     bflb_gpio_set(gpio, _pin);
  67.     //延时400ns
  68.     for (volatile int i = 0; i < 20; i++);
  69.     bflb_gpio_reset(gpio, _pin);
  70.     //延时850ns
  71.     for (volatile int i = 0; i < 30; i++);
  72. }

  73. // RGB发送数据.
  74. void sendRGB(uint8_t pin, uint8_t red, uint8_t green, uint8_t blue) {
  75.     for (uint8_t i = 0; i < 8; i++) {
  76.         if (green & 0x80) {
  77.             sendOne(pin);
  78.         } else {
  79.             sendZero(pin);
  80.         }
  81.         green <<= 1;
  82.     }

  83.     for (uint8_t i = 0; i < 8; i++) {
  84.         if (red & 0x80) {
  85.             sendOne(pin);
  86.         } else {
  87.             sendZero(pin);
  88.         }
  89.         red <<= 1;
  90.     }

  91.     for (uint8_t i = 0; i < 8; i++) {
  92.         if (blue & 0x80) {
  93.             sendOne(pin);
  94.         } else {
  95.             sendZero(pin);
  96.         }
  97.         blue <<= 1;
  98.     }
  99. }


  100. // 设置RGB值,如果需要点亮必须调用pixel_show()
  101. void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
  102.     if (n >= strip.num_leds) {
  103.         return;
  104.     }

  105.     strip.leds[n].simple.r = r;
  106.     strip.leds[n].simple.g = g;
  107.     strip.leds[n].simple.b = b;
  108. }

  109. // 刷新RGB.
  110. void pixel_show(void) {
  111.    
  112.         for(int i=0;i<2;i++){
  113.                 for (int i = 0; i < strip.num_leds; i++) {
  114.                         color_t pixel = strip.leds[i];
  115.                         uint8_t r = pixel.simple.r;
  116.                         uint8_t g = pixel.simple.g;
  117.                         uint8_t b = pixel.simple.b;

  118.                         // 根据亮度调整RGB值
  119.                         r = (r * _brightness) >> 8;
  120.                         g = (g * _brightness) >> 8;
  121.                         b = (b * _brightness) >> 8;
  122.                         if(_mode==1)sendRGB(strip.pin_num, r, g, b);
  123.                         else sendRGB(strip.pin_num, g, r, b);
  124.             }
  125.                 // 延时50us用于刷新数据
  126.                 bflb_mtimer_delay_us(50);
  127.         }

  128. }

  129. //全部写入一种颜色
  130. void Pixel_set_all_color(uint8_t red, uint8_t green, uint8_t blue)
  131. {

  132.     for (int i = 0; i < strip.num_leds; i++)
  133.         {
  134.                 strip.leds[i].simple.g = green;
  135.                 strip.leds[i].simple.r = red;
  136.                 strip.leds[i].simple.b = blue;
  137.         }
  138. }

  139. //关闭所有
  140. void pixel_clear()
  141. {
  142.         for (int i = 0; i < strip.num_leds; i++)
  143.         {
  144.                 strip.leds[i].simple.g = 0;
  145.                 strip.leds[i].simple.r = 0;
  146.                 strip.leds[i].simple.b = 0;
  147.         }
  148.         pixel_show();
  149. }

  150. //=============
  151. uint32_t color(uint8_t r, uint8_t g, uint8_t b) {
  152.            return ((uint32_t)r << 16) | ((uint32_t)g <<  8) | b;
  153. }

  154. // 颜色转换
  155. uint32_t wheel(uint8_t WheelPos)
  156. {
  157.         WheelPos = 255 - WheelPos;
  158.           if(WheelPos < 85) {
  159.             return color(255 - WheelPos * 3, 0, WheelPos * 3);
  160.           }
  161.           if(WheelPos < 170) {
  162.             WheelPos -= 85;
  163.             return color(0, WheelPos * 3, 255 - WheelPos * 3);
  164.           }
  165.           WheelPos -= 170;
  166.           return color(WheelPos * 3, 255 - WheelPos * 3, 0);
  167. }
  168. // RGB写入32位颜色值
  169. uint8_t pixel_set_color(uint16_t index, uint32_t col)
  170. {
  171.         uint8_t r = (uint8_t)(col >> 16);
  172.           uint8_t g = (uint8_t)(col >>  8);
  173.           uint8_t b = (uint8_t)col;

  174.         if (index < strip.num_leds)
  175.         {
  176.                 strip.leds[index].simple.r = r;
  177.                 strip.leds[index].simple.g = g;
  178.                 strip.leds[index].simple.b = b;
  179.         }
  180.         else{
  181.                 return 1;
  182.         }
  183.         return 0;
  184. }

  185. // 彩虹循环
  186. void pixel_rainbow(uint8_t tim) {
  187.   uint16_t i, j;

  188.   for(j=0; j<256; j++) {
  189.     for(i=0; i<strip.num_leds; i++) {
  190.       pixel_set_color(i, wheel((i+j) & 255));
  191.     }
  192.     pixel_show();
  193.     bflb_mtimer_delay_ms(tim);
  194.   }
  195. }

  196. // 流光溢彩
  197. void pixel_rainbowCycle(uint8_t tim) {
  198.   uint16_t i, j;

  199.   for(j=0; j<256*5; j++) {
  200.     for(i=0; i< strip.num_leds; i++) {
  201.               pixel_set_color(i, wheel(((i * 256 / strip.num_leds) + j) & 255));
  202.     }
  203.     pixel_show();
  204.     bflb_mtimer_delay_ms(tim);
  205.   }
  206. }



  207. //=====单色单灯流水
  208. void demo_0(uint16_t R,uint8_t G,uint8_t B,uint8_t spd)
  209. {
  210.         
  211. for(int b=0; b<3; b++) {
  212.                 pixel_clear();         
  213.                 for(int c=b; c<strip.num_leds; c += 3) {
  214.                         setPixelColor(c, R, G, B);
  215.                 }
  216.                 pixel_show();
  217.                 bflb_mtimer_delay_ms(spd);  
  218.         }

  219. }

  220. //====多彩单灯流水
  221. void demo_1(uint16_t spd)
  222. {
  223.         for(int b=0; b<3; b++) {
  224.                         pixel_clear();         
  225.                         for(int c=b; c<strip.num_leds; c += 3) {
  226.                                 uint8_t r =rand() % 256;
  227.                                 uint8_t g =rand() % 256;
  228.                                 uint8_t b =rand() % 256;
  229.                                 setPixelColor(c, r, g, b);
  230.                         }
  231.                         pixel_show();
  232.                         bflb_mtimer_delay_ms(spd);
  233.                 }

  234. }

  235. //=====单色扩散===
  236. void demo_2(uint16_t spd){
  237.         uint8_t r = rand() % 256;
  238.         uint8_t g = rand() % 256;
  239.         uint8_t b =rand() % 256;
  240.         uint8_t x0 = strip.num_leds/2-1;
  241.         uint8_t x1 = strip.num_leds/2+1;
  242.         setPixelColor(strip.num_leds/2,r,g,b);
  243.         for(uint8_t i=0;i<strip.num_leds/2+1;i++){
  244.                 setPixelColor(x0,r,g,b);
  245.                 setPixelColor(x1,r,g,b);
  246.                 pixel_show();
  247.                 bflb_mtimer_delay_ms(spd);
  248.                 x0--;
  249.                 x1++;
  250.         }
  251. }

  252. // 13x14点阵字
  253. void showtext(uint8_t (*letter)[13]) {
  254.   for (int y = 0; y < 14; y++) {
  255.     for (int x = 0; x < 13; x++) {
  256.       if (letter[y][x]) {
  257.         setPixelColor(y * 13 + x, 255, 255, 255);
  258.       } else {
  259.         setPixelColor(y * 13 + x, 0, 0, 0);
  260.       }
  261.         }
  262.   }
  263.   pixel_show();
  264. }


  265. #endif
复制代码

main.c文件
  1. #include "WS2812.h"
  2. #include "board.h"


  3. float data;
  4. int main(void)
  5. {
  6.     board_init();
  7.     WS2812_init(24, 182, 5,2); // 引脚号,灯珠数,亮度,发送顺序(rgb,gbr)
  8.     bflb_mtimer_delay_ms(100);
  9.     while (1) {
  10.         
  11.         pixel_rainbow(60); //灯效
  12.         // pixel_rainbowCycle(60);
  13.         // demo_2(60);
  14.         bflb_mtimer_delay_ms(1000);
  15.     }
  16. }
复制代码

楼楼在代码中添加了一些注释,关于灯效的话,大家可以自己研究,楼楼承认楼楼是个小菜鸟,很不专业,如果代码哪里有问题大家可以自行修改!










本帖被以下淘专辑推荐:

回复

使用道具 举报

王乐乐 | 2023-9-3 09:44:23 | 显示全部楼层
666
回复

使用道具 举报

jkernet | 2023-9-3 19:00:35 来自手机 | 显示全部楼层
高质量帖子,感谢分享。
回复 支持 反对

使用道具 举报

Mr.Tail | 2023-9-5 09:09:13 | 显示全部楼层
这个帖子质量是真的高
回复 支持 反对

使用道具 举报

Mr.Tail | 2023-9-5 09:09:27 | 显示全部楼层
大佬还是持续输出 666
回复 支持 反对

使用道具 举报

开发板 | 2023-9-5 09:41:40 | 显示全部楼层
感谢分享
回复

使用道具 举报

iiv | 2023-9-13 20:14:58 | 显示全部楼层
666
回复

使用道具 举报

Pine | 2023-11-25 22:57:47 | 显示全部楼层
这是不是可以用Lightpack 连接ip:udpport 做个流光溢彩
回复 支持 反对

使用道具 举报

cnfulishe | 2024-3-27 16:34:43 | 显示全部楼层
楼主太厉害了!加油,点个赞
回复 支持 反对

使用道具 举报

1055173307 | 2024-4-2 12:40:59 | 显示全部楼层
学习
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则