前言
之前就答应过大家要把ATtiny85芯片玩出更多花样。用ATtiny85控制WS2812灯珠,我们可以玩出花来,甚至做成点阵屏幕都可以。
这一期主要是做一个圣诞节彩灯。显示Merry Christmas,用于圣诞节装(划掉)~~B~~装扮。
彩灯板的字母内部细节排列和整体布局,我参考了另一位大神的作品,这位大神是使用ESP32做的
https://mc.dfrobot.com.cn/thread-273244-1-1.html?tdsourcetag=s_pctim_aiomsg
一、硬件
1.材料与原理图
硬件包括:
电路板:
ATtiny85开发板,1个
滑动变阻器,2个
按动开关,1个
电阻5-10KΩ,1个
3针插座,1个
电容,1个
DC母头,1个
彩灯板:
亚克力板300mm*400mm,1块
WS2812灯珠,200个
0.6mm铜丝,10米
电容,规格随意,2个
得力502胶带点胶细管,1瓶
2.实物图参考
二、软件
1.软件说明
通过HSV2RGB来实现色彩的平滑过渡。
通过滑动变阻器ADC采集,控制色彩变幻的速度和灯珠亮度。
通过按键来切换闪烁模式。
不多说了,直接上源代码。
2.源代码
/******djddb制作******/
#include <WS2811.h>
//#include "DigiKeyboard.h" //调试用的
#define NUM_LEDS 40 //你的灯珠数量
#define DATA_PIN 1 //RGB输出针脚
#define ADC_PIN1 1 //这里其实是ADC1编号, 而不是引脚号, 对应PB2引脚
#define ADC_PIN2 3 //这里其实是ADC3编号, 而不是引脚号, 对应PB3引脚
/*
ADC0-PB5
ADC1-PB2
ADC2-PB4
ADC3-PB3
*/
DEFINE_WS2811_FN(WS2811RGB, PORTB, 1)
RGB_t rgb[1]; //1 for 1 pixel
uint8_t g,r,b;
uint8_t i;
uint16_t Hueu = 0;
uint8_t satu = 100;
uint8_t mode = 0; //初始化闪烁模式0
uint8_t pressStatus = 1; //上一次按键的状态
uint8_t Brigthness = 20; //初始化亮度20
uint16_t delayms = 300; //初始化变幻延时300ms
uint8_t red[NUM_LEDS],green[NUM_LEDS],blue[NUM_LEDS];
void HSV2RGB(uint16_t hue, uint8_t saturation , uint8_t value)
{
uint16_t hi = (hue / 60) % 6;
uint16_t F = 100 * hue / 60 - 100 * hi;
uint16_t P = value * (100 - saturation) / 100;
uint16_t Q = (10000 - (F * saturation)) / 100;
Q = value * Q / 100; //得单独拿出来乘,不然的话Q值超过uint16的范围,结果会出错。可能是因为ATtiny85是8位单片机不支持uint32
uint16_t T = (10000 - (saturation * (100 - F))) / 100;
T = value * T / 100; //同上
switch (hi)
{
case 0:
red[0] = value;
green[0] = T;
blue[0] = P;
break;
case 1:
red[0] = Q;
green[0] = value;
blue[0] = P;
break;
case 2:
red[0] = P;
green[0] = value;
blue[0] = T;
break;
case 3:
red[0] = P;
green[0] = Q;
blue[0] = value;
break;
case 4:
red[0] = T;
green[0] = P;
blue[0] = value;
break;
case 5:
red[0] = value;
green[0] = P;
blue[0] = Q;
break;
default:
red[0] = Brigthness;
green[0] = Brigthness;
blue[0] = Brigthness;
}
red[0] = red[0] * Brigthness / 100; //如果不做brightness调节的话直接*255/100就行
green[0] = green[0] * Brigthness / 100;
blue[0] = blue[0] * Brigthness / 100;
//DigiKeyboard.println(red[0],DEC); //这里是调试用的
}
void setup() {
pinMode(1,OUTPUT); //P1脚是输出脚,接灯珠的DI
pinMode(0,INPUT_PULLUP); //P0脚是按键脚,监测按键状态切换闪烁模式
delay(10);
for(i = 0; i < NUM_LEDS; i++)
{
red[i] = Brigthness;
green[i] = Brigthness;
blue[i] = Brigthness;
}
for(i = 0; i < NUM_LEDS; i++)
{
rgb[r].r = red[i];
rgb[g].g = green[i];
rgb[b].b = blue[i];
WS2811RGB(rgb, ARRAYLEN(rgb)); //开机先显示全白色
}
//delay(1000);
//DigiKeyboard.println("Hey, Merry Christmas!");
delay(1000);
}
void loop() {
for(i = NUM_LEDS-1; i > 0; i--) //后一个灯珠延续前一个灯珠的颜色,做颜色滚动效果
{
red[i] = red[i-1];
green[i] = green[i-1];
blue[i] = blue[i-1];
}
HSV2RGB(Hueu, satu, 100); //HSV中V值默认100,不做颜色明暗变化,只做色相和饱和度变化
if (mode <= 1)
{
for(i = 0; i < NUM_LEDS; i++) //0,1两种闪烁模式,每个灯珠颜色不同
{
rgb[r].r = red[i];
rgb[g].g = green[i];
rgb[b].b = blue[i];
WS2811RGB(rgb, ARRAYLEN(rgb)); //WS2812B显示颜色
}
}
else
{
for(i = 0; i < NUM_LEDS; i++) //2,3两种闪烁模式,所有灯珠颜色相同
{
rgb[r].r = red[0];
rgb[g].g = green[0];
rgb[b].b = blue[0];
WS2811RGB(rgb, ARRAYLEN(rgb));
}
}
//0脚接切换开关,读取0脚状态决定颜色变化方式
if (digitalRead(0) == LOW && pressStatus == 1)
{
delay(20); //按键消抖
if (digitalRead(0) == LOW && pressStatus == 1)
{
mode = mode + 1;
}
}
pressStatus = digitalRead(0) == LOW?0:1;
if (mode >3)
{mode = 0;}
if (mode%2 == 1) {
Hueu = random(0,360); //mode为奇数则P0脚高电平颜色随机变幻
//DigiKeyboard.println("Hueu");
//DigiKeyboard.println(Hueu,DEC);
} else { //mode为偶数则P0脚底电平颜色顺序变幻
Hueu = Hueu + 3;
if(Hueu > 359)
{Hueu = 0;}
}
delayms = (1024-analogRead(ADC_PIN1))*5; //用滑动电阻来调节灯光变幻频率
Brigthness = (1024-analogRead(ADC_PIN2))/4; //用滑动电阻来调节灯光亮度
//DigiKeyboard.println("delayms");
//DigiKeyboard.println(delayms,DEC);
delay(delayms);
}
总结
效果图可以参考我的B站视频:
https://www.bilibili.com/video/bv1mD4y1Q78V
软件实现起来,还是很容易的,ATtiny85的flash和RAM也都够用,主要是硬件部分用502胶粘灯珠,然后一个一个焊接很耗时间,大家可以动手做起来,家里或者办公室都可以挂上,圣诞节人前显圣。