可设置小夜灯

基于 CH554 实现一个小夜灯。

当下的小夜灯普遍存在着痛点:

1.待机时间短

2.颜色不可调,夜间太亮光线刺眼

3.点亮时间不可调,不方便使用

为此,制作了这样一个小夜灯:使用 18650 电池,同时外壳设计上预留了最够的空间,可以根据用户需要自行扩展加大电池通量。颜色和点亮时间可以用过串口自行设置。

核心部件有2个,一个是 HC-SR602 人体红外感应模块;另外一个是CH554 单片机芯片。此外,外部还有TP4056充电模块,18650电池,XT1861B502MR-G升压芯片,5V开关芯片和SN74AHC1G32DBVR或门芯片。

基本原理是 18650和TP4056充电模块配合工作,负责充放电管理。TP4056充电模块自带一个TypeC接口可以用于充电。当18650放电到2.4V时,TP4056充电模块自动停止工作防止过放。然后XT1861芯片负责将2.4-4.2V电压升压到5V 提供给HC-SR602 人体红外感应模块使用。当这个有人触发红外感应模块后,模块输出到或门芯片,经过运算后用于触发SY6280AAC进行供电。之后,CH554 根据存储的颜色控制 WS2812 LED 发光。同时根据设定的时间控制前面提到的或门。这样就可以实现即便人体红外感应模块输出停止工作之后,仍然输出5V。

HC-SR602模块主要参数(在底板上)

  • 工作电压:3.3V-15V;
  • 静态电流:20uA;
  • 感应距离:最大5M;建议0-3.5M;
  • 信号电平输出:H=3.3V(检测到周围有人体);L=0V(检测周围无人体);

XT1861产品特点(在底板上)

·       最高效率:94%

·       最高工作频率:300KHz

·       低静态电流:15µA

·       输出电压:1.8V~5.0V(步进 0.1V)

·       输入电压:0.9V~6.5V

·       低纹波,低噪声 小体积封装

这里设计的是主控部分,如果想整体工作起来需要配合底板。具体项目在 https://oshwhub.com/zoologist/ch554-xiao-ye-deng-20250510

这里主控部分完整的主要功能是:

1.接收来自串口的,LED 颜色和时长的设定;

2.工作之后负责控制LED 颜色

电路图:

PCB 设计:

 代码使用 Arduino 完成:

#ifndef USER_USB_RAM
#error "This example needs to be compiled with a USER USB setting"
#endif
#include "src/userUsbCdc/USBCDC.h"
#include
#include "DataFlash.H"
#include "include/ch5xx.h"
 
#define NUM_LEDS 2
#define COLOR_PER_LEDS 3
#define NUM_BYTES (NUM_LEDS*COLOR_PER_LEDS)
__xdata uint8_t ledData[NUM_BYTES];
 
#define BIT1 2
 
// USB 串口 Buffer
uint8_t recvStr[6];
uint8_t recvStrPtr = 0;
// 之前保存的颜色值
uint8_t rValue, gValue, bValue;
uint16_t TimeLighting;
 
// 定义电源控制引脚
#define POWERCTRL 15
// 定义LED信号线
#define LEDCOLOR 14
#define NEOPIXELSHOW neopixel_show_P1_4
 
unsigned long ElspLighten = 0;
unsigned long Elsp = 0;
 
void SetLEDColor(uint8_t r, uint8_t g, uint8_t b) {
  for (uint8_t i = 0; i   {
    set_pixel_for_GRB_LED(ledData, i, r,g,b);
    NEOPIXELSHOW(ledData, NUM_BYTES);
    delay(10);
  }
}
void setup() {
  // 供电引脚接管电源
  pinMode(POWERCTRL, OUTPUT);
  digitalWrite(POWERCTRL, HIGH);
 
  // LED 颜色控制
  pinMode(LEDCOLOR, OUTPUT);
 

  USBInit();
 
  // 读取颜色信息
  Flash_Op_Check_Byte1 = 0x00;
  Flash_Op_Check_Byte2 = 0x00;
  ReadDataFlash(0, 1, &rValue);
  ReadDataFlash(1, 1, &gValue);
  ReadDataFlash(2, 1, &bValue);
 
  // 读取时长
  ReadDataFlash(3, 2, &TimeLighting);
 
  // 这里需要写成这样,避免上电亮一下的问题
  delay(10);
  //set_pixel_for_GRB_LED(ledData, 0, 0, 0, 0);
  //NEOPIXELSHOW(ledData, NUM_BYTES);
  SetLEDColor(0,0,0);
  delay(10);
 
  // 读取之前保存的灯颜色
  //set_pixel_for_GRB_LED(ledData, 0, rValue, gValue, bValue);
  //NEOPIXELSHOW(ledData, NUM_BYTES);
  SetLEDColor(rValue, gValue, bValue);
  delay(100);
 
  ElspLighten = millis();
}
 
void Enter_DeepSleep(void)
{
  // 第一步:关闭所有外设模块
  SAFE_MOD = 0x55;       // 进入安全模式
  SAFE_MOD = 0xAA;       // 解锁寄存器写保护
  PCON &= ~BIT1;         // 确保PD位初始为0
  IE_EX = 0x00;          // 关闭扩展中断
  IE = 0x00;             // 关闭所有中断
  TCON = 0x00;           // 关闭定时器控制
  TMOD = 0x00;           // 关闭定时器模式
  SAFE_MOD = 0x00;       // 恢复安全模式
 
  // 第二步:设置IO口为低功耗状态
  P1_DIR_PU = 0x00;         // 所有IO设为输入模式
  P3_DIR_PU = 0x00;         // 所有IO设为输入模式
 
  // 第三步:进入停机模式
  SAFE_MOD = 0x55;       // 二次确认安全模式
  SAFE_MOD = 0xAA;
  PCON |= BIT1;           // 置位PD位进入停机模式
  PCON |= BIT1;           // 推荐重复写入确保执行
 
  while (1);
}
 

void loop() {
  while (USBSerial_available()) {
    char serialChar = USBSerial_read();
    recvStr[recvStrPtr++] = serialChar;
 
    if (recvStrPtr == 5) {
      // 测试命令
      if ((recvStr[0] == 0x55) && (recvStr[1] == 0xCC)) {
        USBSerial_print(rValue);
        USBSerial_flush();
        USBSerial_print(gValue);
        USBSerial_flush();
        USBSerial_print(bValue);
        USBSerial_flush();
        USBSerial_println(TimeLighting);
        USBSerial_flush();
      }
 
      // 设置颜色
      if ((recvStr[0] == 0x55) && (recvStr[1] == 0xAA)) {
        // 记录收到的颜色信息
        rValue = recvStr[2];
        gValue = recvStr[3];
        bValue = recvStr[4];
 
        // 将颜色信息写入 eeprom
        Flash_Op_Check_Byte1 = DEF_FLASH_OP_CHECK1;
        Flash_Op_Check_Byte2 = DEF_FLASH_OP_CHECK2;
        uint8_t result = WriteDataFlash(0, &recvStr[2], 3);
        if (result == 0) {
          // 写入成功
          USBSerial_println(result);
          USBSerial_flush();
        } else {
          // 写入失败
          USBSerial_println(result);
          USBSerial_println("f1");
          USBSerial_flush();
        }
 
        //set_pixel_for_GRB_LED(ledData, 0, rValue, gValue, bValue);
        //NEOPIXELSHOW(ledData, NUM_BYTES);
        SetLEDColor(rValue, gValue, bValue);
 
      }
 
      // 设定时长的命令
      if ((recvStr[0] == 0x55) && (recvStr[1] == 0xBB)) {
        // 记录收到的颜色信息
        TimeLighting = (recvStr[2]) + (recvStr[3] 200) {
    recvStrPtr = 0;
    Elsp = millis();
  }
 
  // 到达点亮的时间后关闭,如果是插在电脑上则不关闭
  if ((millis() - ElspLighten > TimeLighting * 1000UL) && (USBConfiged == 0)) {
    // 关灯
    //set_pixel_for_GRB_LED(ledData, 0, 0, 0, 0);
    //NEOPIXELSHOW(ledData, NUM_BYTES);
    SetLEDColor(0, 0, 0);
 
    digitalWrite(POWERCTRL, LOW);
    // 进入省电模式
    Enter_DeepSleep();
  }
 

}

焊接后的实物:

安装后的照片

3D外壳设计图:

完整代码:

完整电路图和PCB:

工作的测试视频

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注