Digispark ATtiny85 单片机点灯大师之圣诞节彩灯Merry Christmas

刘栋
发布于 2020-12-01 / 47 阅读
0
0

Digispark ATtiny85 单片机点灯大师之圣诞节彩灯Merry Christmas

前言

之前就答应过大家要把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.实物图参考

Merry Christmas 01.jpg

Merry Christmas 02.jpg

Merry Christmas 03.jpg

Merry Christmas 04.jpg

二、软件

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胶粘灯珠,然后一个一个焊接很耗时间,大家可以动手做起来,家里或者办公室都可以挂上,圣诞节人前显圣。


评论