开源!成本4元带你做个加湿器!
强度分为3级,占空比分别为9%,27%,68%,大家也可以根据自己调试去修改占空比来达到自己想要的结果,我就只调试了五分钟就定了着仨值。强度的不同会反应在RGB上,我是设置了蓝色,颜色越深就表示强度越大(占空比越大),RGB灭就表示关闭加湿器。电感值选择25uh:800uh的,为什么选这个值的我就不清楚了,我也是参考别人的,咱这么用就行。这个代码不能直接用,因为我在定时器的中断函数里有点修改,还需
今天带大家做一个加湿器,成本仅需四元!
芯片用的Ai8H1K08,也就是我之前心心念念的AI系列(出自STC)
那么为什么选用这个型号呢?
这是因为要驱动雾化片是需要108KHz的PWM,因此需要用到的是16位高级PWM定时器。
然后我选择了价格最低的Ai8H1K08,仅需0.69元。
PCB板的话每月可以免费打两次。
然后雾化片加支架是两块钱,再加上其他物料,七七八八的就差不多四块钱搞定。
其实没什么难点。
唯一要注意的就是压电陶瓷片的驱动电路,也就是雾化片的驱动。
上图的U2就是三脚电感。可以回顾一下我之前的文章。
记得三脚电感的短边接+5V,长边接到雾化片上,公共端接上一个NMOS,NMOS是G极接到我们单片机的PWM上。
三角电感选择25uh:800uh,CD75,0805封装的。
封装什么的无所谓,PCB上对应着改改就行。
电感值选择25uh:800uh的,为什么选这个值的我就不清楚了,我也是参考别人的,咱这么用就行。
PWM的频率要108K,但差一点其实也没关系。
通过调节PWM的占空比可以调整雾化片的雾化强度,但是经过测试,占空比过了50%之后就基本没有变化了。
Ai8H1K08的外围电路仅需俩电容。
其他我就接了俩按键,三个LED,还有一个RGB三色灯。
其实本不需要那么多元器件的,但是Ai8H1K08有十六个引脚,我寻思着不用也是浪费,所以就加上了。
俩按键,一个调加湿强度,一个调定时。
强度分为3级,占空比分别为9%,27%,68%,大家也可以根据自己调试去修改占空比来达到自己想要的结果,我就只调试了五分钟就定了着仨值。
强度的不同会反应在RGB上,我是设置了蓝色,颜色越深就表示强度越大(占空比越大),RGB灭就表示关闭加湿器。
另外仨LED就是拿来做定时用的,最高可以定时仨小时,分别对应三个灯。
硬件就说这么多。
接下来是软件。
软件其实也没很复杂,使用的库函数,别看它是Ai系列,但是一样用的是STC库函数。
代码不多我直接贴下面,有注释,应该都看得懂。
这个代码不能直接用,因为我在定时器的中断函数里有点修改,还需要在对应的文件里简单改一下。
就是类似外部中断一样,通过读取一个可以外部访问的变量来判断是否触发中断。但是定时器中断里需要自己去写。
#include "STC8G_H_GPIO.h"
#include "STC8G_H_Delay.h"
#include "STC8H_PWM.h"
#include "STC8G_H_Timer.h"
#include "STC8G_H_NVIC.h"
#include "STC8G_H_Exti.h"
#define WS2812B_IN P37
// G、R、B
uint8 color[3] = {0, 0, 0};
uint8 hour = 0;
uint8 minute = 0;
uint8 second = 0;
// 复位
void WS2812B_SendReset(void) {
unsigned char data i, j;
WS2812B_IN = 0; // 拉低80us
i = 2;
j = 219;
do {
while (--j)
;
} while (--i);
}
// 发送1码
void WS2812B_SendOne(void) {
WS2812B_IN = 1; // 拉高延时0.6us
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
WS2812B_IN = 0; // 拉低延时0.3us
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();
}
// 发送0码
void WS2812B_SendZero(void) {
WS2812B_IN = 1; // 拉高延时0.3us
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();
WS2812B_IN = 0; // 拉低延时0.6us
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
// 发送自定义RGB颜色
void WS2812B_SendColor(void) {
uint8 i, j;
WS2812B_SendReset();
for (i = 0; i < 3; ++i) {
for (j = 0; j < 8; ++j) {
if (color[i] & (0x80 >> j)) // 高位在前
WS2812B_SendOne();
else
WS2812B_SendZero();
}
}
}
// 初始化PWM
void PWM_Init(void){
PWMx_InitDefine PWMx_InitStructure;
PWMx_InitStructure.PWM_Mode = CCMRn_PWM_MODE1; // 模式1
PWMx_InitStructure.PWM_Duty = 0; // 阈值
PWMx_InitStructure.PWM_EnoSelect = ENO1P; // 通道1的正通道
PWMx_InitStructure.PWM_Period = 220; // 自动重装载寄存器 220 ≈ 108k的频率
PWMx_InitStructure.PWM_DeadTime = 0; // 死区时间
PWMx_InitStructure.PWM_MainOutEnable = ENABLE; // 使能输出
PWMx_InitStructure.PWM_CEN_Enable = ENABLE; // 使能计数器
PWM_Configuration(PWM1, &PWMx_InitStructure); // 初始化PWM1
PWM_Configuration(PWMA, &PWMx_InitStructure); // 初始化PWMA
PWMA_CC1P_HighValid();
PWM1_USE_P10P11();
}
// 初始化GPIO口
void GPIO_Init(void){
P1_MODE_OUT_PP(GPIO_Pin_3); // LED1
P1_MODE_OUT_PP(GPIO_Pin_4); // LED2
P1_MODE_OUT_PP(GPIO_Pin_5); // LED3
P3_MODE_OUT_PP(GPIO_Pin_7); // RGB
P3_MODE_IN_HIZ(GPIO_Pin_2); // Mode按键
P3_MODE_IN_HIZ(GPIO_Pin_3); // Time按键
P3_PULL_UP_ENABLE(GPIO_Pin_2); // 加上上拉电阻
P3_PULL_UP_ENABLE(GPIO_Pin_3);
P13 = 1;
P14 = 1;
P15 = 1;
}
// 初始化外部中断 俩按键
void EXTI_Init(void){
EXTI_InitTypeDef initer;
initer.EXTI_Mode = EXT_MODE_Fall; // 下降沿触发
Ext_Inilize(EXT_INT0, &initer);
Ext_Inilize(EXT_INT1, &initer);
NVIC_INT0_Init(ENABLE, Priority_1); // 使能INT0,优先级1
NVIC_INT1_Init(ENABLE, Priority_1); // 使能INT1,优先级1
}
void Timer_Init(void) {
// 每25ms中断一次.
TIM_InitTypeDef initer;
initer.TIM_Mode = TIM_16BitAutoReload; // 模式0,16位自动重装载寄存器.
initer.TIM_ClkOut = DISABLE; // 失能可编程时钟输出
initer.TIM_ClkSource = TIM_CLOCK_12T; // 12T工作模式
initer.TIM_Value = 15536; // 计数寄存器和重装载寄存器的值设为15536
initer.TIM_Run = ENABLE; // 定时器,启动!
Timer_Inilize(Timer0, &initer);
ET0 = 0; // 先关闭中断
NVIC_Timer0_Init(ENABLE, Priority_2); // 使能定时器0的NVIC中断
}
// 修改PWM的占空比,控制压变陶瓷片的强度
void ChangePWM(uint8 val){
PWMx_Duty duty;
duty.PWM1_Duty = val;
UpdatePwm(PWM1, &duty);
}
void main(void){
uint16 timeCount = 0;
EAXSFR(); /* 扩展寄存器访问使能 */
GPIO_Init();
PWM_Init();
EXTI_Init();
Timer_Init();
EA = 1;
WS2812B_SendColor();
while(1){
if(WakeUpSource == 1){ // Mode按键按下
WakeUpSource = 0; // 清除标志
delay_ms(5); if(P32) break; // 这行可加可不加,因为已经有电容滤波消抖了
if(color[2] == 0){
color[2] = 3;
ChangePWM(20);
}else if(color[2] == 3){
color[2] = 10;
ChangePWM(60);
}else if(color[2] == 10){
color[2] = 30;
ChangePWM(150);
}else if(color[2] == 30){
color[2] = 0;
ChangePWM(0);
}
WS2812B_SendColor();
}
if(WakeUpSource == 2){ // Time按键按下
WakeUpSource = 0; // 清除标志
delay_ms(5); if(P33) break; // 这行可加可不加,因为已经有电容滤波消抖了
if(hour == 0 && minute == 0 && second == 0){ // 没有定时任务
minute = 59;
second = 59;
ET0 = 1; // 开启定时器
P13 = 0;
}else if(hour == 0 && (minute!= 0 || second != 0)){ // 定时时间在0~1小时内
hour = 1;
P14 = 0;
}else if(hour == 1){ // 定时时间在1~2小时内
hour = 2;
P15 = 0;
}else if(hour == 2){ // 定时时间在2~3小时内
P13 = 1;
P14 = 1;
P15 = 1;
ET0 = 0; // 关闭定时器
hour = 0; minute = 0; second = 0;
}
}
if(TimeWakeUp == 1){
TimeWakeUp = 0;
if(++timeCount >= 40){ // 每过1秒
timeCount = 0;
if(second == 0){ // 秒数不够减
if(minute == 0){ // 分数不够减
if(hour == 0){ // 小时数也不够减,那么关闭最后一个LED,关闭定时器,关闭加湿器
ET0 = 0;
P13 = 1; // 灭第一个LED
ChangePWM(0);
}else{ // 小时数够减
hour--; // 小时数-1
minute = 59;// 将分数补上
second = 59;// 将秒数BUS
if(hour == 0) P14 = 1; // 如果原本有1小时,那么灭第二个LED
else P15 = 1; // 如果原本有2小时,那么灭第三个LED
}
}else{ // 分数够减
minute--; // 分数-1
second = 59;// 秒数补上
}
}else{ // 秒数够减
second--; // 秒数-1
}
}
}
}
}
我开源到立创开源平台了,在那边可以直接查看原理图和PCB,用户名直接搜“折途”。
更多推荐
所有评论(0)