当前位置: 首页 > news >正文

Arduino入门教程​​​​​​​:12、WS2812B

飞书文档https://x509p6c8to.feishu.cn/docx/B5EhdBBego2mDXxesvfctQnDnKd

WS2812B是一款全彩LED控制IC,单总线控制。

接线说明:

注意线的颜色

   “三角形符号代表方向

接反点不亮

接上TypeC烧录接口

基于手册时序实现WS2812B控制:

由手册可知 WS2812B的供电电压在3.7V~5.3V,一般5V供电就可以了。

信号时序如下图,要注意高低电平的时间一定要控制在规格书的要求范围内。WS2812B可以级联,每个灯接收的是24bit数据(GRB颜色值),D1灯在收到24bit数据后,会把数据保存,如果还收到数据,会通过DO脚传给D2。

  • 0码:高电平持续200ns - 380ns后跳变为低电平,低电平持续580ns - 1us;
  • 1码:高电平持续580 - 1us后跳变为低电平,低电平持续580ns - 1us;
  • Resset码:低电平保持时间大于280us

驱动WS2812B需要纳秒级别的延时,arduino 的函数delay(xx);或者Microsecond();只能实现毫秒或者微秒级别的延时,所以我们需要根据自己写延时函数满足纳秒延时。

一般单片机执行NOP();指令都有固定的指令周期,但是ESP32的arduino sdk可能由于封装多层的原因,实测并不线性,所以我们用示波器测试了337ns 600ns 280us几个延时函数。

void delay_337_ns()
{for (int i = 0; i < 1; i++){NOP();}
}void delay_600_ns()
{uint32_t count = 10;for (int i = 0; i < count; i++){NOP();}
}void delay_280_us()
{uint32_t count = 280 * 40;for (uint32_t i = 0; i < count; i++){NOP();}
}

根据手册时序要求,我们可以实现0码、1码、RESET码

/*** @brief 发送0 Code**/
void set_0_num()
{digitalWrite(PIN_LED, HIGH);delay_337_ns();digitalWrite(PIN_LED, LOW);delay_600_ns();
}/*** @brief 发送1 Code**/
void set_1_num()
{digitalWrite(PIN_LED, HIGH);delay_600_ns();digitalWrite(PIN_LED, LOW);delay_600_ns();
}/*** @brief 发送reset**/
void set_reset()
{digitalWrite(PIN_LED, LOW);delay_280_us();
}

最后,我们就可以按照标准色卡的RGB值,实现数据的传输啦.

#include <Arduino.h>// 信号IO引脚
#define PIN_LED 16// 颜色
typedef struct
{uint8_t R;uint8_t G;uint8_t B;
} t_color;void delay_337_ns()
{for (int i = 0; i < 1; i++){NOP();}
}void delay_600_ns()
{uint32_t count = 10;for (int i = 0; i < count; i++){NOP();}
}void delay_280_us()
{uint32_t count = 280 * 40;for (uint32_t i = 0; i < count; i++){NOP();}
}/*** @brief 发送0 Code**/
void set_0_num()
{digitalWrite(PIN_LED, HIGH);delay_337_ns();digitalWrite(PIN_LED, LOW);delay_600_ns();
}/*** @brief 发送1 Code**/
void set_1_num()
{digitalWrite(PIN_LED, HIGH);delay_600_ns();digitalWrite(PIN_LED, LOW);delay_600_ns();
}/*** @brief 发送reset**/
void set_reset()
{digitalWrite(PIN_LED, LOW);delay_280_us();
}/*** @brief 根据每Bit数值设置发送0Code / 1Code** @param dat*/
void ws2812b_writebyte(uint8_t dat)
{for (uint8_t i = 0; i < 8; i++){// 先发送高位if (dat & 0x80) // 该位为1set_1_num();else // 该位为0set_0_num();dat <<= 1;}
}/*** @brief 按手册写入G R B 24bit数据** @param pColor*/
void ws2812b_writecolor(t_color *pColor)
{ws2812b_writebyte(pColor->G);ws2812b_writebyte(pColor->R);ws2812b_writebyte(pColor->B);
}/*** @brief 多LED控制   //  BL_Color 0x000000   //关---清空颜色//  W_Color  0xFFFFFF    //白光//  R_Color  0xFF0000   //红色//  G_Color  0x00FF00   //绿色//  B_Color  0x0000FF   //蓝色**/
void ws2812b_more_led_test()
{t_color temp;temp.R = 0x00;temp.B = 0xFF;temp.G = 0x00;const int PIXEL_NUM = 10;while (true){for (uint8_t i = 0; i < PIXEL_NUM; i++){ws2812b_writecolor(&temp);}set_reset();}
}/*** @brief 单颗LED控制**/
void ws2812b_one_led_test()
{t_color temp;temp.R = 0x00;temp.B = 0xFF;temp.G = 0x00;while (true){ws2812b_writecolor(&temp);set_reset();}
}void setup()
{Serial.begin(9600);Serial.printf("setup\n");pinMode(PIN_LED, OUTPUT);
}void loop()
{ws2812b_one_led_test();// ws2812b_more_led_test();
}

到这里,你已经可以自己手写WB2812B的控制代码了,但是你会发现,整体代码实现还是有点多的,那Arduino有没有一些封装好的库可以让我们快速使用呢?答案当然是有的,那就是FastLED。

基于FastLED实现灯珠控制

1、添加FastLED库依赖

2、编写代码

#include <FastLED.h>// 一共有多少个LED灯?
#define NUM_LEDS 60
// 绿色的数据线接在几号端口?
#define DATA_PIN 5
// 初始化LED灯数组
CRGB leds[NUM_LEDS];void setup()
{/*NEOPIXEL:控制灯珠的类型LED_PIN:控制板上使用的IO端口leds:灯带NUM_LEDS:灯珠的总数量*/FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);// 初始化LEDS.showColor(CRGB(255, 0, 0));delay(500);LEDS.showColor(CRGB(0, 255, 0));delay(500);LEDS.showColor(CRGB(0, 0, 255));delay(500);LEDS.showColor(CRGB(0, 0, 0));
}void loop()
{
}

光随屏动效果-串口版本

代码实现

实现原理:

  1. LED灯板上电后,发送Ada字符串到电脑,电脑端的软件读取到Ada字符后,初始化成功。
  2. 电脑端软件读取屏幕颜色值,拼凑为指令Ada+hi+lo+checksum+rgb数组,下发给LED灯板。
  3. LED灯板接收到Ada字符后,读取hi lo checksum校验码信息,验证正确后,读取rgb值实现灯颜色控制。
#include <FastLED.h>//一共有多少个LED灯?
#define NUM_LEDS 60
//绿色的数据线接在几号端口?
#define DATA_PIN 5 
//通讯口波特率
#define serialRate 115200//口令,可以理解为通讯协议,对口号,芝麻开门的意思
uint8_t prefix[] = {'A', 'd', 'a'}, hi, lo, chk, i;
//初始化LED灯数组
CRGB leds[NUM_LEDS];void setup() {//NEO像素色彩 IO引脚 led数组 led灯数量FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);//初始化LEDS.showColor(CRGB(255, 0, 0));delay(500);LEDS.showColor(CRGB(0, 255, 0));delay(500);LEDS.showColor(CRGB(0, 0, 255));delay(500);LEDS.showColor(CRGB(0, 0, 0));Serial.begin(serialRate);//发送对口号Serial.print("Ada\n");
}void loop() {//等待串口返回口号for(i = 0; i < sizeof prefix; ++i) {waitLoop: while (!Serial.available()) ;;//读取串口数据,直至收到Ada口令词退出if(prefix[i] == Serial.read()) continue;// otherwise, start overi = 0;goto waitLoop;}// 读取Hi, Lo, Checksum while (!Serial.available()) ;;hi=Serial.read();while (!Serial.available()) ;;lo=Serial.read();while (!Serial.available()) ;;chk=Serial.read();//如果校验和不匹配,返回等待if (chk != (hi ^ lo ^ 0x55)) {i=0;goto waitLoop;}memset(leds, 0, NUM_LEDS * sizeof(struct CRGB));//读取传输数据并设置 LED 值for (uint8_t i = 0; i < NUM_LEDS; i++) {byte r, g, b;   while(!Serial.available());r = Serial.read();while(!Serial.available());g = Serial.read();while(!Serial.available());b = Serial.read();leds[i].r = r;leds[i].g = g;leds[i].b = b;}//刷新点亮FastLED.show();
}

电脑端配置

1、电脑一台+流光溢彩PCBA一套+USB线(有线连接)

使用USB线连接电脑与板卡,板卡上电,然后在设备管理器中找到对应COM口,记得烧录代码实现部分的固件哦。

2、把灯带贴到显示器或支撑板后

3、安装Prismatik软件

安装过程比较简单,全部默认点击下一步,安装完成即可。参考飞书文档

4、配置

安装完毕后,会直接弹出配置向导,如果没有弹出,就去点桌面右下角,有个月亮图标,右击它,Settings

下面是点 Setting后弹出的界面,在Device页面,点“Run Configuration wizard”,打开设置向导

在这里,无线连接和有线连接唯一的区别是,无线选择局域网方式,有线选择时需选择COM口方式。

有线连接:需要设置COM口,电脑连接板卡后,打开系统设备管理器查看

进入下一步,设置好名称后,就是配置灯与显示器的位置关系了:

1、选择显示器,多个显示器请选择贴LED灯的那个

2、设置LED数量

3、配置LED灯位置,我们可以看到屏幕边上的1-60就是实际要采集的LED颜色位置,可以根据我们贴LED的位置进行拖拽修改,直接按默认不修改也可以

配置完成后按下一步,按默认完成配置即可,完成配置后,我们可以在屏幕菜单栏右击点击Turn on即可完成流光溢彩。

http://www.lqws.cn/news/445879.html

相关文章:

  • 不会PLC,怎么学上位机?
  • 在 Mac 上配置 Charles,抓取 iOS 手机端接口请求
  • 写实数字人:开启教学新纪元,重塑教育生态
  • 股票心理学习篇:交易的人性弱点 - 频繁交易
  • 基于 Apache POI 实现的 Word 操作工具类
  • 目标检测之YOLOV11自定义数据使用OBB训练与验证
  • 用Java将PDF转换成GIF
  • 关于嵌入式编译工具链与游戏移植的学习
  • S32K328打断点调试进入main函数之前的准备工作
  • 如何保证MySQL与Redis数据一致性方案详解
  • 中科米堆全自动三维光学测量航空部件尺寸测量分析
  • 白热化买量竞争下,消除手游如何巧借“创意”破局?
  • OpenLayers 加载投影坐标GeoTIFF影像
  • 微信小程序canvas实现抽奖动画
  • react forwardRef和readux的connect冲突,导致ref.current获取不到值
  • Linux中的阻塞信号与信号原理
  • 主流防火墙策略绕过漏洞的修复方案与加固实践
  • MCAL(7)-AutoSar存储
  • 前端如何通过 Blob 下载 Excel 文件
  • angular 图斑点击,列表选中并滚动到中间位置
  • 网页后端开发(基础5--JDBC VS Mybatis)
  • linux路由
  • 响应式数据框架性能深度分析报告(@type-dom/signals)
  • PromptWizard:强化学习或者多Agent 优化提示词
  • SpringBoot定时监控数据库状态
  • 191. 位1的个数
  • vs code配置go开发环境以及问题解决 could not import cannot find package in GOROOT or GOPATH
  • Linux树莓派项目实战:外网访问、PWM呼吸灯、超声波测距与驱动开发
  • Linux内核中通过perf_event监控内存访问的硬件断点触发流程
  • LINUX 619 NFS rsync