首先是购买配件
nodemcu选择便宜的esp8266
灯带用了以前剩下的ws2801,(大家如果买的话建议买ws2811/2812)
刷nodemcu固件
默认固件不支持ws2801,去官网适配支持ws2801的固件刷入esp8266
win下开发:https://www.jianshu.com/p/af28ee8a3d06
win下开发:https://www.jianshu.com/p/a2482b542f45
mac刷固件详细过程:https://www.jianshu.com/p/e06c621d32fb
引出ws2801四个引脚
四根线分别是
vcc(我买的对应5v)
ck (时钟线)
si (信号线)
gnd (gcc)
其中注意vcc和gnd要外接usb电源(如果是12v的也需要额外的12v电源)不要让nodemcu提供5v电源,会把板子烧了
接线
引出的ck线接D3口(gpio0)
引出的si线接D4口 (gpio2)
代码
因为是内建模块,所以用法很简单
初始化
ws2801.init(0,2)
将所有灯泡熄灭
ws2801.write(string.char(0,0,0):rep(100))
设置灯的颜色
ws2801.write(string.char(0,50,0))
其中数值第一位为红色,第二位为蓝色,第三位为绿色,数值的范围是0-255,这和官方文档不一样,官方文档对应的蓝色和绿色是对调的,这不影响实现的最终效果
最后的代码
ws2801.init(4,2)
ws2801.write(string.char(0,0,0):rep(100))
function HSL(hue, saturation, lightness)
local chroma = (1 - math.abs(2 * lightness - 1)) * saturation
local h = hue/60
local x =(1 - math.abs(h % 2 - 1)) * chroma
local r, g, b = 0, 0, 0
if h < 1 then
r,g,b=chroma,x,0
elseif h < 2 then
r,b,g=x,chroma,0
elseif h < 3 then
r,g,b=0,chroma,x
elseif h < 4 then
r,g,b=0,x,chroma
elseif h < 5 then
r,g,b=x,0,chroma
else
r,g,b=chroma,0,x
end
local m = lightness - chroma/2
return math.floor((r+m)*255),math.floor((g+m)*255),math.floor((b+m)*255)
end
turntype =4
loopNum = 0
direction = 1
--tmr.delay(1000000)
--ws2801.write(string.char(0,50,0))
ledNum = 25
ledColors = ledNum*3
ledPool = {}
ledPoolTo = {}
for i=1, ledColors,3 do
ledPool[i] = 0
ledPool[i+1] = 0
ledPool[i+2] = 0
local cr,cg,cb = HSL(math.random(0,255),1,.1)
ledPoolTo[i]=cr
ledPoolTo[i+1]=cg
ledPoolTo[i+2]=cb
-- ledPoolTo[i]=math.random(65,90)
-- print(cr,cg,cb)
end
function turnLed()
local str = ""
for i=1, ledColors, 3 do
-- ledPool[i]=ledPool[i]+(ledPoolTo[i]-ledPool[i])/10
-- ledPool[i+1]=ledPool[i+1]+(ledPoolTo[i+1]-ledPool[i+1])/10
-- ledPool[i+2]=ledPool[i+2]+(ledPoolTo[i+2]-ledPool[i+2])/10
str=str..string.char(ledPoolTo[i],ledPoolTo[i+1],ledPoolTo[i+2])
end
ws2801.write(str)
-- print(str)
end
function turnLedTo()
local str = ""
if turntype==1 then
for i=1, ledColors, 3 do
local cr,cg,cb = HSL(math.random(0,255),1,.05)
ledPoolTo[i]=cr
ledPoolTo[i+1]=cg
ledPoolTo[i+2]=cb
str=str..string.char(ledPoolTo[i],ledPoolTo[i+1],ledPoolTo[i+2])
end
elseif turntype==3 then
loopNum=(loopNum+1)%4
for i=1, ledColors, 3 do
if (i+loopNum)%4~=0 then
str=str..string.char(0,0,0)
else
local cr,cg,cb = HSL(math.random(0,255),1,.05)
ledPoolTo[i]=cr
ledPoolTo[i+1]=cg
ledPoolTo[i+2]=cb
str=str..string.char(ledPoolTo[i],ledPoolTo[i+1],ledPoolTo[i+2])
end
end
elseif turntype==2 then
loopNum=(loopNum+1)%ledNum
for i=1, ledColors, 3 do
if i~=(loopNum*3+1) then
str=str..string.char(0,0,0)
else
local cr,cg,cb = HSL(math.random(0,255),1,.05)
ledPoolTo[i]=cr
ledPoolTo[i+1]=cg
ledPoolTo[i+2]=cb
str=str..string.char(ledPoolTo[i],ledPoolTo[i+1],ledPoolTo[i+2])
end
end
elseif turntype==4 then
if math.random(0,100)>90 then
direction = -direction
end
loopNum=loopNum+direction
if loopNum<0 then
loopNum = ledNum-1
elseif loopNum>=ledNum then
loopNum = 0
end
for i=1, ledColors, 3 do
if i~=(loopNum*3+1) then
str=str..string.char(0,0,0)
else
local cr,cg,cb = HSL(math.random(0,255),1,.05)
ledPoolTo[i]=cr
ledPoolTo[i+1]=cg
ledPoolTo[i+2]=cb
str=str..string.char(ledPoolTo[i],ledPoolTo[i+1],ledPoolTo[i+2])
end
end
end
ws2801.write(str)
end
--tmr.stop(0)
--tmr.alarm(0, 50, tmr.ALARM_AUTO, turnLed)
tmr.stop(1)
tmr.alarm(1, 50, tmr.ALARM_AUTO, turnLedTo)
function onBtnEvent()
local tt = turntype-1
tt=(tt+1)%4
turntype=tt+1
print(turntype)
if turntype==2 then
tmr.stop(1)
tmr.alarm(1, 100, tmr.ALARM_AUTO, turnLedTo)
elseif turntype==4 then
tmr.stop(1)
tmr.alarm(1, 50, tmr.ALARM_AUTO, turnLedTo)
elseif turntype==3 then
tmr.stop(1)
tmr.alarm(1, 1000, tmr.ALARM_AUTO, turnLedTo)
else
tmr.stop(1)
tmr.alarm(1, 2000, tmr.ALARM_AUTO, turnLedTo)
end
end
gpio.mode(3, gpio.INT, gpio.PULLUP)
gpio.trig(3, "up", onBtnEvent)
--color1 = HSL(100,.5,.5)
--print(color1[0])
--print(color1[1])
--print(color1[2])
ps:我将io口从3,4改为2,4(gpio4,2),这是因为nodemcu上的物理按键对应的D3口,在不外扩的情况下可以用来切换彩灯的显示效果