yhyf_heart 发表于 2008-6-11 10:01:42

家中冰箱温控器坏了,自已DIY一个,程序控制流程不太清楚,各位能不能给点意见。

家中冰箱温控器坏了,自已DIY一个,硬件结构:M8+18B20+继电器。软件控制流程大概是这样:
1、上电延时2分钟。
2、检测冰箱冷藏室温度,是否高于10度,若高于10度,继电器闭合。
3、检测冰箱冷藏室温度,是否低于4度,若低于4度,继电器断开。
4、每次输出时间间隔大于或等于两分钟,保护压缩机。
循环 2 - 4.

这样会不会有问题啊?温度范围有没有问题呢。大约设成多少合适?请各位多多指教,谢谢!

watercat 发表于 2008-6-11 10:07:16

冰箱冷藏室很难做到温度一致的,如果整体到了4度,那么必然有些地方要结冰了,而这样还需要另一套除霜算法

另外,闲得没事用mega8干什么?tiny25不是更好?内置温度传感器,省得你折腾什么18B20了……而且抗干扰性能也明显好过M8……

csg0203 发表于 2008-6-11 10:34:21

个人觉得,没必要这样做,买个温控器不到10元,最多一天内可修好,如果自己做,成本不说,还又费时费力,再说,这东西也就这点功能,就是想学习也没多大东西可学,还不如来点难的,有用的,比如做个清扫机器人什么的,就不用自己干活了,呵呵。

个人意见,只供参考。

yhyf_heart 发表于 2008-6-11 10:46:42

谢谢各位,我手头刚好有个M8闲置,就打算做个玩玩。
买的温控器安装麻烦,修过一次了,不理想。现在用起来太费电了,温度调到最大冷藏室都会冰。

hl0716 发表于 2008-6-11 10:49:25

要程序吗,我做过类式的,不过18b20反映速度太慢了,建议使用其他的!

yerdak 发表于 2008-6-11 10:56:53

把18B20、tiny25放在冰箱里采温度,冷冻室怎么办?冷藏室结霜、化霜呢?

冰箱的控制器坏了,传感器应该没有坏,冰箱所谓的温度传感器,其实就是NTC套了一个铁壳加了环氧填充并引出来两根线的东西,冷冻室一个,冷藏室一个。如果是老式的话自己去买两个,大约零售3-4元。加合适的电阻分压进入AD就可以了。

化霜你根据实际情况设定为压缩机连续运转某一个时间,或长时间低于某一个温度后进行化霜,冰箱里面有化霜电热丝。

压缩机保护除了防频繁启动(一般设为停机后3分钟才能重新启动),还要防止长时间运转,比如连续运转了6个小时之后,就要停机报故障。

rober 发表于 2008-6-11 13:42:23

这我已经用51做好了,现在还工作用着,想当时我的家人夸我的神态,再苦再累也值得

yhyf_heart 发表于 2008-6-11 14:25:17

其实我家的那个是机械式温度开关只有冷藏室顶部一个,长时间不用,开不了机,触点被氧化。
我修时拆开罩子一看完了,一个小铜管子被搞断了,晕!是靠这个小铜管子里面的气体检测温度的,这玩意温度控制精度也太差了。只能换一个,好不容易我同学给我搞了一个,据说要二三十块一个呢。装上后,温度调到最高冷藏室都会冰,用起来太费电,现在家人都没敢用了。这次回老家准备换成我自已做的。板子已焊好,明天上个图给大伙呵呵。


【4楼】 hl0716 :18B20反应用在这个上面应该足够了吧。 程序能不能共享一下?或直接发给我 :yhyf_heart@yahoo.cn 谢谢!


【5楼】 yerdak 大戈:有没有化霜的功能我还不知道呢,是自动化霜吗?什么时间比较合适,每次要多长时间呢?板子上只做了一个继电器,放在盒子里。化霜功能要是没有多大必要的话,我就不改板子了。盒子里没空间。

【6楼】 rober :自已DIY乐趣之一呢。想当时我的家人夸我的神态,再苦再累也值得 !呵呵.

再次谢谢各位,有什么不同的想法,请跟贴。

zldiy 发表于 2008-6-11 15:23:19

我也有兴趣做个玩玩
不指导使用NTC是否合适。公司正好有常温20度5K电NTC,不知道用到冰箱上是否合适

hl0716 发表于 2008-6-11 15:43:07

不指导使用NTC是否合适。公司正好有常温20度5K电NTC,不知道用到冰箱上是否合适
ntc不行哦!

hl0716 发表于 2008-6-11 15:45:26

/*m818b20.c   2008-05-03   
本程序为采用mega8 和18b20的温度采集程序
选用mega8内部8M RC震荡,18b20 数据线接pd4,数据线和vcc间接一4.7k上拉电阻
感谢www.ouravr.com
qq:61870905
msn:houliang@foxmail.com
*/

#include <iom8v.h> //和单片机类型相对应的头文件,选择Atmega8做实验;
#include <macros.h>
#include <stdio.h>
#include <eeprom.h>
#include <MATH.H>
#include <stdlib.h>
#include <STRING.H>
#define uchar unsigned char
#define uint unsigned int
#define LED_NUM    PORTD   //数码管公共端
#define LED_VALUEPORTB   //数码管数据位
#define ADC_KEY    3
#define SOUND_OUT0x08
#define FAN_OUT1   0x01
#define FAN_OUT2   0x02
#define FAN_OUT3   0x04
#define DELAY_MIN1100
uint v = 0;
uchar adc_channel = 0;
uchar hot_warning={34,34,34,45};
uinttemper={5,5,5};//存放温度
uchar setting_mode = 0;
uchar auto_mode = 0x00;
uchar timeh=0x06;
uchar temp2=0;
uchar PWF1=0;
uchar PWFS1=0,PWFS2=0,PWFS3=0;//是否进行调速标志
uchar Fc1,Fc2,Fc3;//计数
void init_1820();//初始化1820                                                                               
write_1820(uchar x); //写参数到1820
uchar read_1820(); //读温度
void delay(uint x);
void disp_led(uchar buffer,uchar control);
void test(void);
long count;
void delay_1ms(void);
//uchar hot_warning={30,35,40,45};//设定风扇启动温度
void delay_nms(unsigned int n);
unsigned int wendu={21,22,23,24};//定义温度存放数组
void temph(unsigned int tx); //电压转换成温度
void display(void);// 显示数据
void display_mode(uchar mo);//模式显示,花样显示
void scandisplay(uint value);//扫描显示数码管
void dc_save(void);//dc 转换结果存储后用
void init_port();//初始化端口
void output(uchar channel,uchar power);//风扇控制 函数 通道风力
unsigned intuiVref_preset=4996;         // 参考电压=2665mV
uchar Lednum={0xDF,0xBF,0x7F};//数码管公共端口
uchardisp_table = {
        0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
        0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x40};
        //共阴数码管       
const uint v_table={
950,1000,1050,1100,1150,1200,1250,1300,1350,1400,//-10-1
1450,1500,1550,1600,1650,1700,1750,1800,1850,1900//0-9
,1950,2000,2050,2100,2150,2200,2230,2260,2290,2320//10-19
,2350,2380,2410,2440,2470,2520,2590,2600,2617,2670//20-29
,2725,2800,2855,2935,2990,3041,3100,3148,3206,3260
,3302,3354,3414,3450,3504,3554,3600,3650,3680,3748
,3778,3818,3850,3889,3936,3986,4008,4015,4059,4089
,4116,4124,4146,4170,4200,4224,4248,4275,4296,4314
,4332,4353,4374,4395,4416,4428,4444,4461,4476,4488
,4502,4528,4544,4552,4562,4574,4584,4594,4602,4612
,4622,4632,4642,4652,4660,4668,4672,4680,4690,4698
,4704,4713,4723,4728,4733,4738,                                               
                                                };
const uchar sound[]={ //?Ρ?誹
        0x45,0x48,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x49,0x4a,
        0x49,0x48,0x48,0x48,0x48,0x48,0x45,0x48,0x4a,0x4a,
        0x48,0x4a,0x4c,0x4c,0x4b,0x4a,0x49,0x49,0x49,0x49,
        0x49,0x4c,0x4b,0x4a,0x4a,0x4a,0x49,0x48,0x48,0x49,
        0x4a,0x4c,0x4b,0x4b,0x4b,0x4b,0x4b,0x46,0x46,0x45,
        0x45,0x45,0x47,0x48,0x49,0x49,0x4a,0x49,0x48,0x48,
        0x48,0x48,0x48,0x48,
        0x00,0x00
};               
uchar temp1;
//uint count;
#define PWM0                        3         //OC0   PB3
#define PWM1A                        5         //OC1APD5
#define PWM1B                        4         //OC1BPD4
#define PWM2                        7         //OC2   PD7


#define   Fosc_TIME2      (64*10)             //TIME2 比较中断频率=采样率*AD通道数*工频50Hz的倍数
volatile unsigned char T2PWM;       
void main(void)
{   
    uint i,k;
        uchar temh,teml;
        int j;       
init_port();//初始化       
hot_warning = EEPROMread(0x01);//读取报警温度
hot_warning = EEPROMread(0x02);
hot_warning = EEPROMread(0x03);
   for(k=0;k<4;k++) //初始化
      {
           if (hot_warning>120)
          hot_warning=32;
      }       
while(1)
{   // temp_setting(); // 設定                        
            WDR();
                     // scandisplay(3000);
                                //for(i=0;i<1000;i++)   //每次转换需要延时200ms以上
               // delay(1000);      
                init_1820();      //复位18b20
                write_1820(0xcc);   // 发出转换命令
                write_1820(0x44);
                delay(400);
                               scandisplay(count);
                init_1820();
                WDR();
                write_1820(0xcc);//发出读命令
               //scandisplay(count);
                                write_1820(0xbe);
                teml=read_1820();//读数据
                temh=read_1820();
                count=((temh*256+teml)*6.25)/10;//计算具体温度
                scandisplay(count);
                          WDR();
            scandisplay(count);      
                           // disp_led(0,1);   //显示温度
               scandisplay(count);
                                for(i=0;i<20;i++)   //每次转换需要延时200ms以上
               {
                               scandisplay(count);
                               //delay(1000);
                           }
       //scandisplay(temper);

    }


}

//io口初始化
void init_port()
{
       OSCCAL=0X9d;   //系统时钟校准,不同的芯片和不同的频率,
        //DDRB=0x03;   //定义B口的PB0、PB1为输出口
        //DDRC=0x30;   //定义C口的PC4和PC5为输出口
        //PORTD = 0x01;//pd2.pd3.pd4输入 pd0 输出
    //DDRD= 0x01;
    //CLKPR = 0x80;
   // CLKPR = 0x00;   
    DDRB = 0xff;
    PORTB = 0x00;
    DDRC = 0xff;
    PORTC = 0x00;
       DDRB = 0xff;
   PORTB = 0xff;
    DDRD= 0xFF;//定义PD0喇叭输出 PD2 PD3 PD4 按键输入 PD5 PD6 PD7 风扇输出
        PORTD = 0xF7; //初始化 端口 数据
        WDR();      //看门狗计数清零
    WDTCR=0x0F;    //使能watchdog,并且,采用2048K分频,典型溢出时间5V时2.1S
    //adc_init();                // 使能ADC
        //timer2_init();             // 使能AD转换
        CLI();
    ADMUX = (1<<REFS0);    //选择基准
    ADCSRA = (1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1);        
       MCUCR = 0x00;
   GICR= 0x00;
    TIMSK = 0x15; //timer interrupt sources       
        SEI();       //开放中断
        //WDTCSR = 0x0F;
        //PORTB=0B00000010; //PB1口输出高电平,PB0口输出低电平,关闭绿灯,红灯亮
        //delay_nms(500); //延时1秒
        temp1=1;
        temp1=2;
        temp1=3;
        //test();
        timer0_init();
        timer1_init();
}
void delay(uint x)//1.5us左右
{
          while(x)
         {
            x--;
         }
}

//TIMER0 initialize - prescale:1024
// desired value: 60mSec
// actual value: 59.904mSec (0.2%)
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x16; //set count
TCCR0 = 0x05; //start timer
}
#pragma interrupt_handler timer0_ovf_isr:10
void timer0_ovf_isr(void)
{
TCNT0 = 0x16; //reload counter value
}
//数码管 扫描显示
void scandisplay(uint value)
{   
      uchar i,j,k,l;
          uint tempvalue;
      uchar led_data;
if ((value & 0x8000)==0x8000)
{
      value &= 0x7fff;
      led_data = 15; // 顯示負號
}
else
{
      value &= 0x7fff;
           if(value<999)//需要加小数点
      {
       k=1;
           led_data = value/100;
       }
   else//大于100度去掉小数点
   {
      k=0;
          value=value/10;
          led_data = value/100;
   }          
};
led_data = value%100/10;
led_data = value%100%10;
if((led_data==0)&&(led_data==0))
{//如果只有1位数的时候,将高位的0去掉
led_data=16;
led_data=16;
k=0;//去掉小数点
}
    for (j=0;j<10;j++) //刷新20次 避免数据跳动
   {
       for (i=0;i<3;i++)
      {
                LED_VALUE = disp_table];
      if((i==1)&&(k==1))
      {   
            LED_VALUE |= 0x80; // 加上小數點
      }
                LED_NUM&=Lednum;//对应位数码管点亮
                delay_nms(10);
           LED_NUM|= 0xE0;//只保留高3位为1
      };
   };
}
void delay_1ms(void)//1ms延时函数
{
unsigned int i;
for (i=0;i<150;i++);
WDR();    //清看门狗
}
void delay_nms(unsigned int n)//延时n毫秒
{
unsigned int i;
for (i=0;i<n;i++)//执行n次1毫秒延时
delay_1ms();
}
#pragma interrupt_handler adc_isr:iv_ADC
void adc_isr(void)
{uint temp;
temp = ADCL;
temp |= (int)ADCH<<8;
temp = (48*temp)/10;
v += temp;   
}
void get_adc_value(uchar adc_pin)
{
uchar i;
v = 0x0000;
ADMUX = (1<<REFS0)|adc_pin;
{
ADCSRA |= (1<<ADSC);
delay_nms(1);
ADCSRA &= ~(1<<ADSC);
}
}
uint get_degree(void)
{
uchar x,y;
uint v_big,v_small,v_step;
if (v<100) return 0x83E7; // 當沒有信號時顯示-99.9錯誤
for (x=0;x<135;x++) // 查表
{
      if ( v>= v_table) // 找出電壓區域 //
      {
      v_big = v_table; // 區域 高段
      v_small = v_table; //區域 低段
      v_step = (v_big - v_small)/10; // 把區域細分成10份
      for (y=0;y<10;y++) // 細分比較
      {
            v_small += v_step;
            if (v < v_small) // 得出結果
            {
            v = x*10+y;// 其中x*10 為整數部分, y 為小數部分
            if (x<10) // 少於10時為負溫度
            {
                           // v -= 400; // 0 度修正
                  v |= 0x8000; // 加入負號標記
                                  //v=v;
            }
            else
            {
               v -= 100; // 0 度修正
            }
                       
                  return v;//返回温度
            };
      };
      };
      WDR();
}
return v;   
}
uchar get_key_value(void)
{
        get_adc_value(ADC_KEY);
        if (v < 250)
        {
                return 0;
        }
        else
        {
                if ((v > 1000)&&(v < 1300))
                {
                        return 1;//1150mv
                }
                else
                {
                        if ((v > 1300)&&(v < 2200))
                        {
                                return 2;//1948
                        }
                        else
                        {
                                if ((v > 2200)&&(v < 3500))
                                {
                                        return 3;//3000mv
                                }
                                else
                                {
                                        return 0;
                                }
                        }
                }
        }
}

void temp_setting(void)
{
        uchar key;
        key = get_key_value();

        if(key==2)
        {
                adc_channel++;

                if (adc_channel>2) //切换显示路数
                  {
                   adc_channel = 0;
                   }
       scandisplay(adc_channel+1);
           scandisplay(adc_channel+1);
           scandisplay(adc_channel+1);
           scandisplay(adc_channel+1);               
        }
        if(key==3)
        {
           if (auto_mode==0xff) // 自動模式
      {
                auto_mode = ~auto_mode;//退出 自动模式
                }
               
                if (adc_channel==0) //设置模式
                {
                        adc_channel = 1;
                        auto_mode = ~auto_mode;//3路自动切换
                }
                adc_channel--;               
        }
        while(1)
        {
                get_adc_value(ADC_KEY);
                if(v < 200) //退出当前模式
                {
                        break;
                };
        };       
        if (key==1)
        {
        scandisplay(1+adc_channel);
        scandisplay(1+adc_channel);
        scandisplay(1+adc_channel);       
        scandisplay(1+adc_channel);       
        setting_mode = 1;
        }

        while(setting_mode==1)
        {
                key = get_key_value();
                if(key==1)
                {
            adc_channel++;                                       
                        if (adc_channel>2)
                        {
                                adc_channel = 0;
                                setting_mode = 0;
                                EEPROMwrite(0x01, hot_warning);
                                delay_nms(5);
                                EEPROMwrite(0x02, hot_warning);
                                delay_nms(5);
                                EEPROMwrite(0x03, hot_warning);
                                delay_nms(5);
                        }
           scandisplay(1+adc_channel);
           scandisplay(1+adc_channel);
           scandisplay(1+adc_channel);
           scandisplay(1+adc_channel);                                       
                }
                else
                {
                        if(key==2)
                        {
                          if(hot_warning>105)
                                {
                                hot_warning=30;
                                }
                                else
                                {
                                ++hot_warning;
                                }
                        }
                        else
                        {        if(key==3)
                          {
                          if(hot_warning<1)
                                {
                                hot_warning=30;
                                }
                          else
                                {
                               --hot_warning;
                                }
                                }
                        };
                };
                while(1)
                {
                        get_adc_value(ADC_KEY);
                        if(v < 200)
                        {
                                break;
                        };
                };
                scandisplay(hot_warning*10);
        }
}

//TIMER1 initialize - prescale:1024
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 500mSec
// actual value: 499.968mSec (0.0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0xFF; //setup
TCNT1L = 0xFC;
OCR1AH = 0x07;
OCR1AL = 0xA1;
OCR1BH = 0x07;
OCR1BL = 0xA1;
ICR1H= 0x07;
ICR1L= 0xA1;
TCCR1A = 0x00;
TCCR1B = 0x05; //start Timer
}
void init_1820()
{
         PORTD|=(1<<4);   
         PORTD&=~(1<<4);
         delay(3000);    //480us以上
            PORTD|=(1<<4);
         DDRD&=~(1<<4);
         delay(40);   //15~60us
         while(PIND&(1<<4))
         {
         // disp_led(3,0);
                // for(;;)
               //{}
      }
         DDRD|=(1<<4);
         PORTD|=(1<<4);
         delay(150);   //60~240us
}
write_1820(uchar x)
{   
   uchar m;
         for(m=0;m<8;m++)
         {
            PORTD&=~(1<<4);
               if(x&(1<<m))    //写数据,从低位开始
               PORTD|=(1<<4);
               else
               PORTD&=~(1<<4);
               delay(40);   //15~60us
               PORTD|=(1<<4);
         }
          PORTD|=(1<<4);
}


uchar read_1820()
{   
         uchar temp,k,n;
         temp=0;
         for(n=0;n<8;n++)
            {
                PORTD&=~(1<<4);
                //delay(2);      
                PORTD|=(1<<4);
                //delay(3);   
                DDRD&=~(1<<4);
                k=(PIND&(1<<4));    //读数据,从低位开始
                if(k)
                temp|=(1<<n);
                else
                temp&=~(1<<n);
                delay(50); //60~120us   
                DDRD|=(1<<4);
      }
      return (temp);
}
#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr(void)
{
//compare occured TCNT1=OCR1A
}
#pragma interrupt_handler timer1_ovf_isr:9
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
//TCNT1H = 0xF8; //reload counter high value
TCNT1H = 0xFF;
TCNT1L = 0xFC; //reload counter low value
//PORTD=bitcpl(PORTD,2);// 取反 。。。
// scandisplay(995);
Fc1++;
pwm1();
Fc2++;
Fc3++;
//pwm2();

}

void pwm1(void) // pwm 控制函数
{
//开始 调速控制
if(PWFS1)
{
    //输出
       if(Fc1<45)
       {
       PORTD=bitset(PORTD,0);//打开风扇
       }
    else
   {
   PORTD=bitclr(PORTD,0);//关闭风扇
   }
   if(Fc1>90)
   {
   Fc1=0;
   }
}
   //输出
        if(PWFS2)
        {
       if(Fc2<45)
       {
       PORTD=bitset(PORTD,1);//打开风扇
       }
    else
   {
   PORTD=bitclr(PORTD,1);//关闭风扇
   }
   if(Fc2>90)
   {
   Fc2=0;
   }
   }
   //输出
        if(PWFS3)
        {
       if(Fc3<45)
       {
       PORTD=bitset(PORTD,2);//打开风扇
       }
    else
   {
   PORTD=bitclr(PORTD,2);//关闭风扇
   }
   if(Fc3>90)
   {
   Fc3=0;
   }
   }
}
uchar bitclr(uchar num,uchar bit) /*清除某一位*/
{
uchar bit_value[]={1,2,4,8,16,32,64,128};
return num&~bit_value;
}
uchar bitset(uchar num,uchar bit) /*设置某一位*/
{
uchar bit_value[]={1,2,4,8,16,32,64,128};
return num|bit_value;
}
uchar bitcpl(uchar num,uchar bit) /*取反某一位*/
{
uchar bit_value[]={1,2,4,8,16,32,64,128};
if(num>>bit&0x01==1)
return num&~bit_value;
else
return num|bit_value;
}

hl0716 发表于 2008-6-11 16:07:45

http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_306934.JPG
(原文件名:photo0170.JPG)

zldiy 发表于 2008-6-11 16:38:59

不错的资料,收下了

yhyf_heart 发表于 2008-6-12 16:29:14

图片来了,先上图给各位看一下,软件还没来的及去写。
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_308402.JPG
(原文件名:DSCN3195.JPG)

http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_308403.JPG
(原文件名:DSCN3196.JPG)

http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_308404.JPG
(原文件名:DSCN3197.JPG)

JZcrystalwlh888 发表于 2021-4-13 21:14:13

楼主用的这个程序实际能够运行了吗,还有就是这个控制压缩机不行吧,会挂掉的,
页: [1]
查看完整版本: 家中冰箱温控器坏了,自已DIY一个,程序控制流程不太清楚,各位能不能给点意见。