矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 7875|回复: 17

【参赛】自制家用电子恒温箱

[复制链接]
     
发表于 2022-1-26 19:40:35 | 显示全部楼层 |阅读模式
    一个家用的微波炉因为变压器次级击穿打火而淘汰了,几年前曾经用其中的变压器改制了一个点焊机,但效果不理想,箱体打算改制成恒温箱,但一直没有付诸实施。这次抽出时间,赶在本次大赛结束之前完成了,作为参赛作品献丑了。下面就是改制后家用电子恒温箱外观:
001.jpg

    这是内部的照片:
002.jpg

    一、箱体改造

    下图为改造前的微波炉:
003.jpg

    加热部分使用了一个旧的保健腰带:
004.jpg

    拆出了内部的加热部分,测温传感器使用普通的DHT11,使用三个分别检测箱体内部顶部和底部以及箱体外部的温度:
005.jpg


    先将微波炉大缷八块,拆除了所有可拆解的部件,以便为箱体添加保温材料。在箱体内部先添加了一层薄海棉:
006.jpg

    然后将加热垫放在底部:
007.jpg

    再加上一层保温袋上拆解的保温层,并在顶部和底部各安装了一个温湿度传感器:
008.jpg

    门上也贴了一层保温材料:
009.jpg

    事后测试时发现,由于发热垫在保温层底下,加热的效果不好,最后还是将发热垫移到保温层的上面。
021.jpg

    为了加强保温效果,箱体的外部出添加了一层包装泡沫,这是按照箱体外形裁剪好的泡沫材料:
016.jpg

    用透明胶带将泡沫缠裹在箱体外部:
017.jpg


   二、控制部分改造

    拆除原定时器电机,保留旋钮,利用这个旋钮的开关功能作为恒温箱电源开关:
010.jpg

    原调温旋钮现作调整设定温度用,拆除原来的调温机构,利用原来旋钮的轴来带动旋转编码器。
012.jpg

    由于原来的轴几乎与夹板平,因此首先需要降低夹板位置,以便轴露出来:
013.jpg

    然后将露出来的轴锉成小的六角形,以便插入旋转编码器中:
014.jpg

    最后用热熔胶固定好旋转编码器:
015.jpg


  三,单片机控制部分

    这是首次设计的单片机控制线路:
110.jpg

    这是调试完成后的单片机控制线路:
111.jpg

    这是按照首次线路图设计打样的PCB:
101.jpg

    单片机是利用原有的STM32F030开发板:
102.jpg

    加热控制开关是由双向可控硅BAT204K-600B,因为加热的电流是毫安级别,所以双向可控硅就没有加装散热器。驱动双向可控硅的是MOC3041光耦,同时起到高低压隔离作用,为此在PCB板上还开了隔离槽沟。开始从网上查找的双向可控硅线路测试不成功,几经修改后才达到要求,这是反复修改后的线路板:
103.jpg

    这是线路板背面,可以看到添加的元件及跳线:
104.jpg

    为了方便以后扩展,线路图留有DS1307日历芯片和AT24Cxx存储芯片的位置,还有四个ADC转换及两个按键的位置,目前这些部分尚未焊接元件。
    这是安装好的测试照片:
105.jpg

    恒温箱的操作控制只有电源开关和调整旋钮,向右旋转下部的电源开关旋钮,电源接通,恒温箱开始工作,此时OLED显示屏点亮并显示相关信息,旁边的双色LED灯也会闪亮。OLED屏幕依次显示顶部、底部和外部的温、湿度信息以及设定的温度,这是显示顶部温湿度:
106.jpg

    这是显示底部温湿度:
107.jpg

    这是显示设定温度:
109.jpg


评分

1

查看全部评分

     
 楼主| 发表于 2022-1-26 19:42:56 | 显示全部楼层
  这是单片机控制的代码:
[code]/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "i2c.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"

#include "oled.h"
#include "oledpic.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
volatile uint8_t ms_h,ms;
volatile uint8_t DHT[5][3],Temp;  //Temp=设定温度
//volatile uint8_t dl,ds;    //测试用

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void DisplayMain(void);
void DisplayTemp(uint8_t n);
void Device_Error(void);

void DHT_Error(uint8_t n);
void DHT_GpioDir(uint8_t dir);
uint8_t DHT_GetVal(uint8_t n);

void DelayUs(uint16_t us);

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  uint8_t Led = 0,mode = 0,rol_A,rol_B,rol_D,state,counts = 0,heating = 0,adjust = 0,wait;
  uint16_t average;

       
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC_Init();
  MX_I2C1_Init();
  MX_SPI1_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

  
  HAL_GPIO_WritePin(LD3_G_GPIO_Port,LD3_G_Pin,GPIO_PIN_SET);
  HAL_GPIO_WritePin(LD4_B_GPIO_Port,LD4_B_Pin,GPIO_PIN_SET);
  
  HAL_GPIO_WritePin(GPIOB,DHT11_1_Pin,GPIO_PIN_SET);
  HAL_GPIO_WritePin(GPIOB,DHT11_2_Pin,GPIO_PIN_SET);
  HAL_GPIO_WritePin(GPIOB,DHT11_3_Pin,GPIO_PIN_SET);
  
  HAL_GPIO_WritePin(GPIOB,SK_Pin,GPIO_PIN_SET);    //设置光耦关闭
  
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  OLED_Init();
  
//  OLED_Allfill();

  OLED_Allfill();
  DisplayMain();
  HAL_Delay(3000);

  Temp = 35;
  DHT_GetVal(2);              //获取外部温湿度传感器数据
  DisplayTemp(2);             //显示外部温度

  HAL_Delay(3000);
//  if(Temp<DHT[2][2])
//      Temp = DHT[2][2];       //设定温度初始值按照环境温度(整数部分)
  OLED_ShowNum(30,2,Temp,2,16);
  DisplayTemp(3);             //显示设定温度
  
  rol_A = HAL_GPIO_ReadPin(GPIOB,Roll_A_Pin);  //预先读取滚轮编码器状态
  rol_B = HAL_GPIO_ReadPin(GPIOB,Roll_B_Pin);
  
  while (1)
  {
          //IWDG
//          HAL_IWDG_Refresh(&hiwdg);
          
      //捕获按键操作
          if(HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)){
              HAL_Delay(20);
                  if(HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)){               //按键测试光耦开关
                      if(heating){
                              heating = 0;
                                  HAL_GPIO_WritePin(GPIOB,SK_Pin,GPIO_PIN_SET);    //光耦关闭
                          }
                          else{
                              heating = 1;
                                  HAL_GPIO_WritePin(GPIOB,SK_Pin,GPIO_PIN_RESET);  //光耦开启
                          }
                          wait =  30;
                          HAL_Delay(1000);
                  }
          }
          //捕获滚轮动作
      if((rol_A != HAL_GPIO_ReadPin(GPIOB,Roll_A_Pin)) | (rol_B != HAL_GPIO_ReadPin(GPIOB,Roll_B_Pin))){ //捕获滚轮动作
          adjust = 10;                   //锁定屏幕显示内容10秒
                  rol_A = HAL_GPIO_ReadPin(GPIOB,Roll_A_Pin);  //读取滚轮编码器状态
          rol_B = HAL_GPIO_ReadPin(GPIOB,Roll_B_Pin);

          if(rol_A>0 & rol_B>0)          //起始状态(两个引脚均为高电平)
              state = 0;
          else{
              if(rol_A==0 & rol_B==0)    //第3状态(两个引脚均为低电平)
                  state = 2;
              else{
                  if(state == 0){        //第2状态(判定旋转方向)
                      rol_D = rol_A;
                      state = 1;
                  }
                  else{
                      state = 3;         //第4状态(恢复)
                      counts++;
                  }
              }
          }
      }
          if(counts>0){           //处理滚轮调整结果
                  if(mode<3){
                      mode = 3;       //显示设定温度
                          DisplayTemp(mode);
                  }
              if(rol_D>0)
                          Temp -= counts;
                  else
                          Temp += counts;
                  if(Temp < DHT[2][2]){
                          Temp = DHT[2][2];
                          //设定温度不能低于外部温度
                          OLED_ShowHanzi(0,2,37);  // 已
                          OLED_ShowHanzi(16,2,38); // 是
                          OLED_ShowHanzi(32,2,39); // 最
                          OLED_ShowHanzi(48,2,12); // 低
                          OLED_ShowHanzi(64,2,3);  // 温
                          OLED_ShowHanzi(80,2,7);  // 度
                          OLED_ShowChar(99,2,'0'+Temp/10,16);
                          OLED_ShowChar(109,2,'0'+Temp%10,16);
                          OLED_ShowChar(120,2,127,16);
                  }
                  else if(Temp > 60){
                      Temp = 60;
                          //设定温度不能高于60度
                          OLED_ShowHanzi(0,2,37);  // 已
                          OLED_ShowHanzi(16,2,38); // 是
                          OLED_ShowHanzi(32,2,39); // 最
                          OLED_ShowHanzi(48,2,11); // 高
                          OLED_ShowHanzi(64,2,3);  // 温
                          OLED_ShowHanzi(80,2,7);  // 度
                          OLED_ShowChar(99,2,'6',16);
                          OLED_ShowChar(109,2,'0',16);
                          OLED_ShowChar(120,2,127,16);
                  }
                  else{
                          OLED_Clear(2,2);//清除第3~4行显示
                  }
               
                  counts = 0;         //清除计数值
                  OLED_ShowNum(70,0,Temp,2,16);   // 显示温度整数
          }

      if(ms>99){              // 0.1秒处理开始
          ms = 0;
          ms_h++;
   
                  if(ms_h>9){         // 秒处理开始
                          if(wait>0)
                                  wait--;     // 温控操作延时(隔30秒检测一次)
                          else{
                                  if(0==DHT[4][0]){//计算平均值
                                          average = DHT[2][0];
                                          if(0==DHT[4][1]){
                                              average += DHT[2][1];
                                                  average >>= 1;
                                          }
                                  }
                                  else{
                                          if(0==DHT[4][1])
                                              average += DHT[2][1];
                                          else
                                              average = Temp;
                                  }
                                  
                                  if(Temp>average){ //设定温度低于顶部及底部温度的平均值,导通加热
                                  HAL_GPIO_WritePin(GPIOB,SK_Pin,GPIO_PIN_RESET);  //光耦开启
                      heating = 1;
                                  }
                                  else{
                                  HAL_GPIO_WritePin(GPIOB,SK_Pin,GPIO_PIN_SET);    //光耦关闭
                      heating = 0;
                                  }
                                  wait = 30;// 30秒之后再检测
                          }

              ms_h = 0;
                          HAL_GPIO_WritePin(LD3_G_GPIO_Port,LD3_G_Pin,GPIO_PIN_SET);
                          HAL_GPIO_WritePin(LD4_B_GPIO_Port,LD4_B_Pin,GPIO_PIN_SET);
                          if(Led>0){
                              if(heating>0)// 加热模式,红灯闪亮
                                          HAL_GPIO_WritePin(LD4_B_GPIO_Port,LD4_B_Pin,GPIO_PIN_RESET);
                                  else        // 非加热模式,绿灯闪亮
                                      HAL_GPIO_WritePin(LD3_G_GPIO_Port,LD3_G_Pin,GPIO_PIN_RESET);
                                  Led = 0;    // 设置LED状态为高电平
                          }
                          else
                                  Led = 1;    //为下次亮灯作准备
//                          HAL_GPIO_TogglePin(GPIOB,Led0_Pin);//测试用
//                          HAL_GPIO_TogglePin(GPIOB,Led1_Pin);
                          
                          if(adjust>0){   //设定温度设定操作时延时
                                  adjust--;
                          }
                          else{           //非设定温度操作,正常轮流显示顶部、底部、外部及设定温度
                              if(mode<3){
                      DHT[4][mode] = DHT_GetVal(mode);//读取温湿度传感器数据(0~2),返回值:0=正常,1=失败
                      if(0==DHT[4][mode])
                                                  DisplayTemp(mode); //显示温湿度数据
                                          else
                                                  DHT_Error(mode);   //显示传感器故障信息
                              }
                                  else if(mode==3)
                                      DisplayTemp(mode);     //显示设定温度

                                  
                                  if(mode<9){                 //正常处理
                                          OLED_ShowNum(0,3,wait,2,12);//显示控制操作延时(秒)
                                   mode++;
                                  if(mode>3)  //mode 0=显示顶部温湿度,1=显示底部温湿度,2=显示外部温湿度,3=显示设定温度
                                          mode = 0;
                                          if(1==DHT[4][0] && 1==DHT[4][1])//两个内部测温传感器故障
                                                  mode = 9;           //故障模式
                                  }
                                  if(mode==9){                //尝试再次读取传感器
                                      DHT[4][0] = DHT_GetVal(0);
                                          DHT[4][1] = DHT_GetVal(1);
                                          if(1==DHT[4][0] && 1==DHT[4][1])//两个内部测温传感器故障
                                                  Device_Error();     //显示故障信息
                                          else
                                                  mode = 0;           //恢复正常模式
                                  }
                          }
          }                   // 秒处理结束
      }                       // 0.1秒处理结束
          
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2022-1-26 19:43:31 | 显示全部楼层
/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI14;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSI14State = RCC_HSI14_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.HSI14CalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
  RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_I2C1;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
  PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/***********************************************
* 函数名:DisplayMain(void)
* 作  用:显示主屏幕
* 参  数:无
* 返  回:无
************************************************/
void DisplayMain(void)
{
    uint8_t i;
        OLED_Clear(0,4);
    for(i=0; i<5; i++){
            OLED_ShowHanzi(i*16+24,0,i);
        }
        OLED_ShowStr(0,2,"You Aer Wellcome",16);
        HAL_Delay(2000);
}


/***********************************************
* 函数名:Display_Temp(uint8_t n)
* 作  用:显示温湿度数据
* 参  数:n(传感器号0~2)
* 返  回:无
************************************************/
void DisplayTemp(uint8_t n)
{
    OLED_Clear(0,4);
    switch(n){
        case 0:
            OLED_ShowHanzi(0,0,20);  // 顶
                OLED_ShowHanzi(16,0,23); // 部
                        break;
                case 1:
                        OLED_ShowHanzi(0,0,21);  // 底
                OLED_ShowHanzi(16,0,23); // 部
                        break;
                case 2:
                        OLED_ShowHanzi(0,0,22);  // 外
                OLED_ShowHanzi(16,0,23); // 部
                        break;
                case 3:
                        OLED_ShowHanzi(0,0,5);   // 设
                OLED_ShowHanzi(16,0,6);  // 定
                    OLED_ShowNum(70,0,Temp,2,16);   // 显示温度整数
                    OLED_ShowStr(88,0,".0",16);
                
        }
    OLED_ShowHanzi(32,0,3);          // 温
        OLED_ShowHanzi(48,0,7);          // 度
        OLED_ShowChar(110,0,127,16);     // 显示温度符号
       
        if(n<3){
                OLED_ShowNum(70,0,DHT[2][n],2,16);  // 显示温度整数
        OLED_ShowChar(88,0,'.',16);
        OLED_ShowChar(97,0,DHT[3][n]+48,16);// 显示温度小数
           
        OLED_ShowHanzi(32,2,13);            // 湿
        OLED_ShowHanzi(48,2,7);             // 度
        OLED_ShowNum(70,2,DHT[0][n],2,16);  // 显示湿度整数
        OLED_ShowChar(88,2,'.',16);
        OLED_ShowChar(97,2,DHT[1][n]+48,16);// 显示湿度小数
        OLED_ShowChar(110,2,'%',16);        // 显示湿度符号
               
        }
}

/***********************************************
* 函数名:Device_Error()
* 作  用:温湿度传感器数据错误,恒温箱无法加热
* 参  数:无
* 返  回:无
************************************************/
void Device_Error(void)
{
        OLED_Clear(0,4);
    OLED_ShowHanzi(20,0,26);         // 传
        OLED_ShowHanzi(36,0,27);         // 感
        OLED_ShowHanzi(52,0,28);         // 器
        OLED_ShowHanzi(68,0,29);         // 错
        OLED_ShowHanzi(84,0,30);         // 误
       
    OLED_ShowHanzi(8,2,2);           // 恒
        OLED_ShowHanzi(24,2,3);          // 温
        OLED_ShowHanzi(40,2,4);          // 箱
        OLED_ShowHanzi(56,2,33);         // 无
        OLED_ShowHanzi(72,2,34);         // 法
        OLED_ShowHanzi(88,2,35);         // 加
        OLED_ShowHanzi(104,2,36);        // 热
}


/***********************************************
* 函数名:DHT_Error(uint8_t n)
* 作  用:温湿度传感器数据错误
* 参  数:n  0~2
* 返  回:无
************************************************/
void DHT_Error(uint8_t n)
{
        OLED_Clear(0,2);
        if(0==n)
        OLED_ShowHanzi(0,0,20);      // 顶
        else if(1==n)
                OLED_ShowHanzi(0,0,21);      // 底
        else
                OLED_ShowHanzi(0,0,22);      // 外
        OLED_ShowHanzi(16,0,23);         // 部
    OLED_ShowHanzi(32,0,26);         // 传
        OLED_ShowHanzi(48,0,27);         // 感
        OLED_ShowHanzi(64,0,28);         // 器
        OLED_ShowHanzi(80,0,31);         // 故
        OLED_ShowHanzi(96,0,32);         // 障
}


/***********************************************
* 函数名:DHT_GetVal(void)
* 作  用:同时读取三个温湿度传感器的数据,存放在全局数组DHT中
* 参  数:n=0~2(顶部、底部、外部三个传感器)
* 返  回:0=读取成功,1=读取失败
************************************************/
uint8_t DHT_GetVal(uint8_t n)
{
    uint8_t i,j,dat,retry;
        switch(n){
        case 0:
                DHT_GpioDir(0);         //总线切换到输出模式
                HAL_GPIO_WritePin(GPIOB, DHT11_1_Pin, GPIO_PIN_RESET); //拉低DQ,发送启动信号
                HAL_Delay(20);          //等待18~30ms
                HAL_GPIO_WritePin(GPIOB, DHT11_1_Pin, GPIO_PIN_SET);   //DQ=1
                DelayUs(20);            //主机拉高20~40us
            DHT_GpioDir(1);         //总线切换到输入模式
            retry = 100;
            while((!HAL_GPIO_ReadPin(GPIOB, DHT11_1_Pin))&&retry){
                retry--;
                DelayUs(1);
            }
            if(retry==0){            //低电平响应信号超时
                return 1;
            }
            retry = 100;
            while((HAL_GPIO_ReadPin(GPIOB, DHT11_1_Pin))&&retry){
                retry--;
                DelayUs(1);
            }
            if(retry==0){            //高电平响应信号超时
                return 1;
            }
            for(j=0; j<5; j++){     //持续读入五个字节数据
                dat = 0;
                for(i=0; i<8; i++){
                    retry = 100;
                    while((0==HAL_GPIO_ReadPin(GPIOB, DHT11_1_Pin))&&retry>0){
                        retry--;
                        DelayUs(1);
                    }
                    retry = 100;
                    while((HAL_GPIO_ReadPin(GPIOB, DHT11_1_Pin)>0)&&retry>0){
                        retry--;
                        DelayUs(1);
                    }
                    dat<<=1;        //左移一位
                    if(retry<80)
                        dat|=0x01;
                }
                DHT[j][n] = dat;
            }
                        break;

                case 1:
                DHT_GpioDir(0);         //总线切换到输出模式
                HAL_GPIO_WritePin(GPIOB, DHT11_2_Pin, GPIO_PIN_RESET); //拉低DQ,发送启动信号
                HAL_Delay(20);          //等待18~30ms
                HAL_GPIO_WritePin(GPIOB, DHT11_2_Pin, GPIO_PIN_SET);   //DQ=1
                DelayUs(20);            //主机拉高20~40us
            DHT_GpioDir(1);         //总线切换到输入模式
            retry = 100;
            while((!HAL_GPIO_ReadPin(GPIOB, DHT11_2_Pin))&&retry){
                retry--;
                DelayUs(1);
            }
            if(retry==0){            //低电平响应信号超时
                return 1;
            }
            retry = 100;
            while((HAL_GPIO_ReadPin(GPIOB, DHT11_2_Pin))&&retry){
                retry--;
                DelayUs(1);
            }
            if(retry==0){            //高电平响应信号超时
                return 1;
            }
            for(j=0; j<5; j++){     //持续读入五个字节数据
                dat = 0;
                for(i=0; i<8; i++){
                    retry = 100;
                    while((0==HAL_GPIO_ReadPin(GPIOB, DHT11_2_Pin))&&retry>0){
                        retry--;
                        DelayUs(1);
                    }
                    retry = 100;
                    while((HAL_GPIO_ReadPin(GPIOB, DHT11_2_Pin)>0)&&retry>0){
                        retry--;
                        DelayUs(1);
                    }
                    dat<<=1;        //左移一位
                    if(retry<80)
                        dat|=0x01;
                }
                DHT[j][n] = dat;
            }
                        break;

                case 2:
                DHT_GpioDir(0);         //总线切换到输出模式
                HAL_GPIO_WritePin(GPIOB, DHT11_3_Pin, GPIO_PIN_RESET); //拉低DQ,发送启动信号
                HAL_Delay(20);          //等待18~30ms
                HAL_GPIO_WritePin(GPIOB, DHT11_3_Pin, GPIO_PIN_SET);   //DQ=1
                DelayUs(20);            //主机拉高20~40us
            DHT_GpioDir(1);         //总线切换到输入模式
            retry = 100;
            while((!HAL_GPIO_ReadPin(GPIOB, DHT11_3_Pin))&&retry){
                retry--;
                DelayUs(1);
            }
            if(retry==0){            //低电平响应信号超时
                return 1;
            }
            retry = 100;
            while((HAL_GPIO_ReadPin(GPIOB, DHT11_3_Pin))&&retry){
                retry--;
                DelayUs(1);
            }
            if(retry==0){            //高电平响应信号超时
                return 1;
            }
            for(j=0; j<5; j++){     //持续读入五个字节数据
                dat = 0;
                for(i=0; i<8; i++){
                    retry = 100;
                    while((0==HAL_GPIO_ReadPin(GPIOB, DHT11_3_Pin))&&retry>0){
                        retry--;
                        DelayUs(1);
                    }
                    retry = 100;
                    while((HAL_GPIO_ReadPin(GPIOB, DHT11_3_Pin)>0)&&retry>0){
                        retry--;
                        DelayUs(1);
                    }
                    dat<<=1;        //左移一位
                    if(retry<80)
                        dat|=0x01;
                }
                DHT[j][n] = dat;
            }
        }
    if(DHT[4][n]==DHT[0][n]+DHT[1][n]+DHT[2][n]+DHT[3][n])
        DHT[4][n] = 0;
    else
        DHT[4][n] = 1;
       
        return 0;
}


/***********************************************
* 函数名:DHT_GpioDir(uint8_t dir)
* 作  用:同时设置三个温湿度传感器数据引脚的方向
* 参  数:dir  0=输出(写)、1=输入(读)
* 返  回:无
************************************************/
void DHT_GpioDir(uint8_t dir)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    /*Configure GPIO pin : PtPin */
    GPIO_InitStruct.Pin = DHT11_1_Pin|DHT11_2_Pin|DHT11_3_Pin;
    if(1==dir){
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
    }
        else{
                GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    }
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}


void DelayUs(uint16_t us)
{
    volatile uint8_t i,j;
        for(i=0; i<us; i++)
        for(j=0; j<1; j++);
}




/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

[/code]


    设定湿度的上限为60度,由于不具备制冷功能,所以设定湿度的下限为外部温度,在转动温度旋钮时,数值随转动方向增减,屏幕上显示出设定的温度,达到上下限时数值不再变动,同时会给出中文提示信息。
    为了防止加热元件频繁开关操作,程序以30秒为一个操作时间段,即每隔30秒进行一次判断,执行加热或停止加热操作。在加热时,红色LED灯以2秒的周期闪烁。在关闭加热时,绿色的LED灯以2秒的周期闪烁。
    电源旋钮向左旋到底,内部会响起一声铃声,同时切断全部电源。


    四、使用效果

    1、由于箱体内部的温度靠自然流动,且加热元件在底部,因此上部和下部有少许温差,上部会略高于底部,但对家庭使用应该无影响。
    2、加热部分的功率较低,如果设定的温度与外部环境温度相差比较大的话,升温的时间会比较长,实测从13度升温到35度大约需要一个小时左右,如需快速升温,需要放置热水辅助初期升温。
    3、为减少频繁开关加热元件,程序设置每隔30执行一次开通或关闭加热元件的操作,因此控制的温度会在设定温度高低1~2度范围内变动,这是考虑到家庭使用不需要那么精确,而且测温传感器也是使用最普通的廉价产品,本身也存在不小的测量误差。
   

    五、总结

    这个恒温箱实质上类似保温箱,主要用于小家庭发酵面粉或者酿制米酒,尤其是在冬天,可以确保正常发酵。在冬季也可以短时放置饭菜,以便迟到的家人能吃上热乎乎的饭菜。
回复 支持 反对

使用道具 举报

     
发表于 2022-1-26 20:17:41 | 显示全部楼层
我用泡沫箱做了一个,自制酸奶非常棒,成功率百分百

评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2022-1-26 20:22:19 | 显示全部楼层
jpdd521 发表于 2022-1-26 20:17
我用泡沫箱做了一个,自制酸奶非常棒,成功率百分百


泡沫箱的保温效果会更好,因为密封性能更强
回复 支持 反对

使用道具 举报

     
发表于 2022-1-26 20:32:21 | 显示全部楼层
hujj 发表于 2022-1-26 20:22
泡沫箱的保温效果会更好,因为密封性能更强

保温好的话就省电,但是经过一年发现有点收缩变形,所以,还是你这个成品改装的好

评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
发表于 2022-1-26 22:35:48 | 显示全部楼层
本帖最后由 002 于 2022-1-26 22:45 编辑

      我也做了一个,冬天发面用。比你的电路简单,没必要用单片机。
一个测温电阻,2个3级管,几个电阻,一个可控硅。【或12V继电器】电源用成品12V电源。
控制12V加热线。控制温度在35度以下。【为了安全第一用12V加热线】

显示用微型液晶温度计。泡沫板装在纸箱里。肯定比你的好用,电路太简单我都不好意思发上来。祝你参赛成功。

评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
发表于 2022-1-27 03:33:46 | 显示全部楼层
非常赞

评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2022-1-27 08:41:16 | 显示全部楼层
jpdd521 发表于 2022-1-26 20:32
保温好的话就省电,但是经过一年发现有点收缩变形,所以,还是你这个成品改装的好

泡沫箱也容易损坏和污染,另外只能保温,温度会逐渐降低。使用了电加热的就可以保持在指定的温度范围内,只要不停电就没问题。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2022-1-27 08:52:40 | 显示全部楼层
002 发表于 2022-1-26 22:35
我也做了一个,冬天发面用。比你的电路简单,没必要用单片机。
一个测温电阻,2个3级管,几个电阻, ...

    单片机用在此时似乎有点大才小用,我是手头上闲置了不少开发板,不用白不用 。另外使用单片机不光可以更准确控制温度,还可以扩展诸如定时加热、预约加热等功能,在我的电路图中就预留了日历芯片、存储芯片、ADC转换等扩展功能,这是模拟电路不容易实现的。但模拟电路也有简单、可靠、价廉等优点。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2022-1-27 08:55:22 | 显示全部楼层

谢谢版主夸奖!
回复 支持 反对

使用道具 举报

     
发表于 2022-1-27 11:38:11 | 显示全部楼层
还可以孵小鸡和小鸭子  给孩子们玩儿

评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2022-1-27 11:44:26 | 显示全部楼层
清纯色狼 发表于 2022-1-27 11:38
还可以孵小鸡和小鸭子  给孩子们玩儿

那也许要缩短加热控制周期,让温度控制更加精确一点,还需要添加微风扇让空气稍微流动,缩小箱内各部位的温差。
回复 支持 反对

使用道具 举报

     
发表于 2022-2-18 19:44:00 | 显示全部楼层
做得很好,如果用旧冰箱做,会省很多事。

评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2022-2-18 20:39:20 | 显示全部楼层
chd 发表于 2022-2-18 19:44
做得很好,如果用旧冰箱做,会省很多事。

谢谢夸奖!冰箱的体积通常比较大,家庭使用很少需要那么大体积的。
回复 支持 反对

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies |上传

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-4-26 05:51

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表