ESP8266 + WS2812 颜色、亮度控制

注意别把灯带接反了,哪边是输入确认一下!!

 

刚开始想到的是用STM32中的DMA传输来实现,但是ESP8266 NONOS_SDK中似乎没有这种功能。

可以基于NODEMCU开发,类似NODE.JS的语法来写,懒得学,又要在Linux环境下编译固件(也可以在NODEMCU官网上自己选择需要的功能,编译好了通过邮件发送给你)就放弃了,以后再尝试。

最终还是用安信可的SDK来做。

项目开发期间使用nodemcu的开发板,接线、下载的时候方便多了。

尝试了下面三种方法。

①试过直接用操作IO电平的函数是不行的,频率太低,不知道是什么原因。

②还可以用串口的方法输出数据,只需将串口配置成6位数据位,无奇偶校验,1位停止位(低电平),起始位必须有1位(低电平),这样就可以使每一帧数据都是8位数据(方便计算所需的波特率),再配置电平翻转(这样两边都是高电平),通过控制6位数据位,控制这一帧数据的高电平时间,从而使WS2812区分出0或1(即串口输出的一帧数据对应WS2812接收到的0或者1)。这个方法比较麻烦,但它不是阻塞式的,将数据存储在串口发送缓冲区即可,后面的电平输出由串口发送中断自动完成。具体参考

③基于NONOS_SDK_2.2.0 ,就是安信可官方的那一套,直接用WRITE_PERI_REG函数来将数据输出,该函数在eagle_soc.c 。

贴代码:

Adafruit_NeoPixel.c

#include "Adafruit_NeoPixel.h"
#include "ets_sys.h"
#include "osapi.h"
/*
 #define GPIO_OUTPUT_SET(gpio_no, bit_value) \
	gpio_output_set(bit_value<<gpio_no, ((~bit_value)&0x01)<<gpio_no, 1<<gpio_no,0)
 */

//I just used a scope to figure out the right time periods.
void SEND_WS_0() {
	uint8_t time;
	time = 3;
	while (time--)
		WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1);
	time = 7;
	while (time--)
		WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 0);
}

void SEND_WS_1() {
	uint8_t time;
	time = 7;
	while (time--)
		WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1);
	time = 3;
	while (time--)
		WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 0);
}

void // ICACHE_FLASH_ATTR
WS2812Send_8bit(uint8_t dat) {
	uint16_t i;
	GPIO_OUTPUT_SET(GPIO_ID_PIN(WSGPIO), 0);
	ets_intr_lock();
	uint8_t mask = 0x80;
	uint8_t byte = dat;
	while (mask) {
		if (byte & mask)
			SEND_WS_1();
		else
			SEND_WS_0();
		mask >>= 1;
	}

	ets_intr_unlock();
}

//GRB format,MSB firsr.
void //ICACHE_FLASH_ATTR
WS2812BSend_24bit(uint8_t R, uint8_t G, uint8_t B) {
	WS2812Send_8bit(G);
	WS2812Send_8bit(R);
	WS2812Send_8bit(B);
}
//delay for millisecond
void HAL_Delay(int time) {
	os_delay_us(time * 1000);
}

static uint8_t rBuffer[PIXEL_MAX] = { 0 };
static uint8_t gBuffer[PIXEL_MAX] = { 0 };
static uint8_t bBuffer[PIXEL_MAX] = { 0 };

void setOneColor(uint16_t n, uint32_t c) {
	rBuffer[n] = (uint8_t) (c >> 16);
	gBuffer[n] = (uint8_t) (c >> 8);
	bBuffer[n] = (uint8_t) c;
}

void setAllColor(uint32_t c) {
	uint8_t r, g, b;
	r = (uint8_t) (c >> 16);
	g = (uint8_t) (c >> 8);
	b = (uint8_t) c;
	uint8_t i;
	for (i = 0; i < PIXEL_MAX; i++) {
		rBuffer[i] = r;
		gBuffer[i] = g;
		bBuffer[i] = b;
	}
}

void cleanOneColor(uint16_t n, uint32_t c) {
	rBuffer[n] = 0;
	gBuffer[n] = 0;
	bBuffer[n] = 0;
}

void cleanAllColor() {
	uint8_t i;
	for (i = 0; i < PIXEL_MAX; i++) {
		rBuffer[i] = 0;
		gBuffer[i] = 0;
		bBuffer[i] = 0;
	}
}

void setAllPixel(void) {
	uint8_t i;
	for (i = 0; i < PIXEL_MAX; i++) {
		WS2812BSend_24bit(rBuffer[i], gBuffer[i], bBuffer[i]);
	}
}

uint32_t Color(uint8_t r, uint8_t g, uint8_t b) {
	return ((uint32_t) r << 16) | ((uint32_t) g << 8) | b;
}
uint32_t Wheel(uint8_t WheelPos) {
	WheelPos = 255 - WheelPos;
	if (WheelPos < 85) {
		return Color(255 - WheelPos * 3, 0, WheelPos * 3);
	}
	if (WheelPos < 170) {
		WheelPos -= 85;
		return Color(0, WheelPos * 3, 255 - WheelPos * 3);
	}
	WheelPos -= 170;
	return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

void rainbow(uint8_t wait) {
	uint16_t i, j;
	for (j = 0; j < 256; j++) {
		for (i = 0; i < PIXEL_MAX; i++) {
			setOneColor(i, Wheel((i + j) & 255));
		}
		HAL_Delay(wait);
	}
	setAllPixel();
}
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
	uint16_t i, j;

	for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
		for (i = 0; i < PIXEL_MAX; i++) {
			setOneColor(i, Wheel(((i * 256 / PIXEL_MAX) + j) & 255));
		}
		HAL_Delay(wait);
	}
	setAllPixel();
}
//Theatre-style crawling lights.o??¨¹¦Ì?
void theaterChase(uint32_t c, uint8_t wait) {
	int i, j, q;
	for (j = 0; j < 10; j++) {  //do 10 cycles of chasing
		for (q = 0; q < 3; q++) {
			for (i = 0; i < PIXEL_MAX; i = i + 1)  //turn every one pixel on
					{
				setOneColor(i + q, c);
			}
			HAL_Delay(wait);

			for (i = 0; i < PIXEL_MAX; i = i + 1) //turn every one pixel off
					{
				setOneColor(i + q, 0);
			}
		}
	}
	setAllPixel();
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
	int i, j, q;
	for (j = 0; j < 256; j++) {     // cycle all 256 colors in the wheel
		for (q = 0; q < 3; q++) {
			for (i = 0; i < PIXEL_MAX; i = i + 1) //turn every one pixel on
					{
				setOneColor(i + q, Wheel((i + j) % 255));
			}

			HAL_Delay(wait);

			for (i = 0; i < PIXEL_MAX; i = i + 1) //turn every one pixel off
					{
				setOneColor(i + q, 0);
			}
		}
	}
	setAllPixel();
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
	uint16_t i = 0;
	for (i = 0; i < PIXEL_MAX; i++) {
		setOneColor(i, c);
		HAL_Delay(wait);
	}
}

void //ICACHE_FLASH_ATTR
WS2812B_Init(void) {
	setAllColor(0);
	setAllPixel();
}

void WS2812B_Test(void) {
	//HAL_Delay(500);
	// rainbowCycle(20);
	// theaterChaseRainbow(50);
}

 

Adafruit_NeoPixel.h

#ifndef _Adafruit_NeoPixel_H
#define _Adafruit_NeoPixel_H

#include "c_types.h"
#include "user_interface.h"
#include "ets_sys.h"
#include "gpio.h"

//thanks for https://github.com/cnlohr/ws2812esp8266 
//thanks for https://github.com/adafruit/Adafruit_NeoPixel

#define WSGPIO 0 //must use the ESP8266 GPIO0 as the pin to drive WS2812B RGB LED!!!
//user can change
#define PIXEL_MAX 12//the total numbers of LEDs you are used in your project

//You will have to 	os_intr_lock();  	os_intr_unlock();

//void setAllColor(uint8_t r, uint8_t g, uint8_t b);
void setOneColor(uint16_t n, uint32_t c);
void setAllColor(uint32_t c);
void cleanOneColor(uint16_t n, uint32_t c);
void cleanAllColor(void);

void setAllPixel(void);

uint32_t Color(uint8_t r, uint8_t g, uint8_t b);
uint32_t Wheel(uint8_t WheelPos);
void rainbowCycle(uint8_t wait) ;
void theaterChase(uint32_t c, uint8_t wait);
void theaterChaseRainbow(uint8_t wait);
void colorWipe(uint32_t c, uint8_t wait);
void WS2812B_Test(void);
void ICACHE_FLASH_ATTR WS2812B_Init(void);

uint32_t changeL(uint32_t rgb, float k);

#endif

改变亮度的话看网上别人说的:RGB转HSV后,将V值乘以系数[0,1] ,再HSV转RGB。

发现好像直接将RGB值都乘以系数,结果是一样的。。。

uint32_t changeL(uint32_t rgb, float k) {
	uint8_t r, g, b;
	float h, s, v;
	uint8_t cmax, cmin, cdes;

	r = (uint8_t) (rgb >> 16);
	g = (uint8_t) (rgb >> 8);
	b = (uint8_t) (rgb);

	os_printf("1:  0x%x \r\n", rgb);
	os_printf("1:  %d %d %d \r\n", r, g, b);

	cmax = r > g ? r : g;
	if (b > cmax)
		cmax = b;
	cmin = r < g ? r : g;
	if (b < cmin)
		cmin = b;
	cdes = cmax - cmin;

	v = cmax / 255.0f;
	s = cmax == 0 ? 0 : cdes / (float) cmax;
	h = 0;

	if (cmax == r && g >= b)
		h = ((g - b) * 60.0f / cdes) + 0;
	else if (cmax == r && g < b)
		h = ((g - b) * 60.0f / cdes) + 360;
	else if (cmax == g)
		h = ((b - r) * 60.0f / cdes) + 120;
	else
		h = ((r - g) * 60.0f / cdes) + 240;

	//

	v *= k;

	float f, p, q, t;
	float rf, gf, bf;
	int i = ((int) (h / 60) % 6);
	f = (h / 60) - i;
	p = v * (1 - s);
	q = v * (1 - f * s);
	t = v * (1 - (1 - f) * s);
	switch (i) {
	case 0:
		rf = v;
		gf = t;
		bf = p;
		break;
	case 1:
		rf = q;
		gf = v;
		bf = p;
		break;
	case 2:
		rf = p;
		gf = v;
		bf = t;
		break;
	case 3:
		rf = p;
		gf = q;
		bf = v;
		break;
	case 4:
		rf = t;
		gf = p;
		bf = v;
		break;
	case 5:
		rf = v;
		gf = p;
		bf = q;
		break;
	default:
		break;
	}

	r = (uint8_t) (rf * 255.0);
	g = (uint8_t) (gf * 255.0);
	b = (uint8_t) (bf * 255.0);

	uint32_t returnColor = ((uint32_t) r << 16) | ((uint32_t) g << 8) | b;
	os_printf("2:  %d %d %d \r\n", (int) r, (int) g, (int) b);
	os_printf("2:  0x%x \r\n\r\n", returnColor);
	return returnColor;
}

 

  • 8
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
您好!您想要了解如何使用ESP8266点亮WS2812 LED灯条,以下是一些基本步骤: 1. 将ESP8266连接到WS2812 LED灯条上。可以使用杜邦线将它们连接在一起,确保引脚匹配。WS2812 LED灯条通常有三个引脚:VCC、GND和数据引脚。ESP8266上的GPIO引脚将用作数据引脚。 2. 安装Arduino IDE并将ESP8266板添加到Arduino IDE中。请确保安装了ESP8266 Core扩展程序。这是通过Arduino IDE的工具>管理库>搜索"ESP8266"来完成的。 3. 打开Arduino IDE并创建一个新的项目。然后选择ESP8266板作为目标板。 4. 在代码中包含FastLED库并初始化它,以便在ESP8266上使用。这可通过以下代码行完成: ``` #include <FastLED.h> #define LED_PIN 2 //定义数据引脚 #define NUM_LEDS 10 //定义LED数量 CRGB leds[NUM_LEDS]; //定义用于存储颜色的数组 void setup() { FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); } void loop() { // 将代码添加到此处以控制LED灯的颜色亮度 } ``` 在这个例子中,我们将数据引脚定义为2,有10个LED,颜色储存在`leds`数组中。然后,在`setup()`函数中,我们初始化FastLED库并将WS2812 LED灯条的类型和引脚等信息添加到库中。此后,您可以在`loop()`函数中添加代码来控制LED灯的颜色亮度。 5. 添加代码以控制LED灯的颜色亮度。FastLED库提供了各种函数和方法,可让您轻松控制LED灯的颜色亮度。以下是一个简单的例子,其中设置所有LED的颜色为红色: ``` void loop() { fill_solid(leds, NUM_LEDS, CRGB(255, 0, 0)); // 将所有LED设置为红色 FastLED.show(); // 更新LED灯 } ``` 在这个例子中,我们使用`fill_solid()`函数将所有LED的颜色设置为红色。然后,我们使用`FastLED.show()`函数更新LED灯。 希望这些步骤能帮助您开始使用ESP8266点亮WS2812 LED灯条。如果您需要更多帮助,请随时让我知道。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值