家中冰箱温控器坏了,自已DIY一个,程序控制流程不太清楚,各位能不能给点意见。
家中冰箱温控器坏了,自已DIY一个,硬件结构:M8+18B20+继电器。软件控制流程大概是这样:1、上电延时2分钟。
2、检测冰箱冷藏室温度,是否高于10度,若高于10度,继电器闭合。
3、检测冰箱冷藏室温度,是否低于4度,若低于4度,继电器断开。
4、每次输出时间间隔大于或等于两分钟,保护压缩机。
循环 2 - 4.
这样会不会有问题啊?温度范围有没有问题呢。大约设成多少合适?请各位多多指教,谢谢! 冰箱冷藏室很难做到温度一致的,如果整体到了4度,那么必然有些地方要结冰了,而这样还需要另一套除霜算法
另外,闲得没事用mega8干什么?tiny25不是更好?内置温度传感器,省得你折腾什么18B20了……而且抗干扰性能也明显好过M8…… 个人觉得,没必要这样做,买个温控器不到10元,最多一天内可修好,如果自己做,成本不说,还又费时费力,再说,这东西也就这点功能,就是想学习也没多大东西可学,还不如来点难的,有用的,比如做个清扫机器人什么的,就不用自己干活了,呵呵。
个人意见,只供参考。 谢谢各位,我手头刚好有个M8闲置,就打算做个玩玩。
买的温控器安装麻烦,修过一次了,不理想。现在用起来太费电了,温度调到最大冷藏室都会冰。 要程序吗,我做过类式的,不过18b20反映速度太慢了,建议使用其他的! 把18B20、tiny25放在冰箱里采温度,冷冻室怎么办?冷藏室结霜、化霜呢?
冰箱的控制器坏了,传感器应该没有坏,冰箱所谓的温度传感器,其实就是NTC套了一个铁壳加了环氧填充并引出来两根线的东西,冷冻室一个,冷藏室一个。如果是老式的话自己去买两个,大约零售3-4元。加合适的电阻分压进入AD就可以了。
化霜你根据实际情况设定为压缩机连续运转某一个时间,或长时间低于某一个温度后进行化霜,冰箱里面有化霜电热丝。
压缩机保护除了防频繁启动(一般设为停机后3分钟才能重新启动),还要防止长时间运转,比如连续运转了6个小时之后,就要停机报故障。 这我已经用51做好了,现在还工作用着,想当时我的家人夸我的神态,再苦再累也值得 其实我家的那个是机械式温度开关只有冷藏室顶部一个,长时间不用,开不了机,触点被氧化。
我修时拆开罩子一看完了,一个小铜管子被搞断了,晕!是靠这个小铜管子里面的气体检测温度的,这玩意温度控制精度也太差了。只能换一个,好不容易我同学给我搞了一个,据说要二三十块一个呢。装上后,温度调到最高冷藏室都会冰,用起来太费电,现在家人都没敢用了。这次回老家准备换成我自已做的。板子已焊好,明天上个图给大伙呵呵。
【4楼】 hl0716 :18B20反应用在这个上面应该足够了吧。 程序能不能共享一下?或直接发给我 :yhyf_heart@yahoo.cn 谢谢!
【5楼】 yerdak 大戈:有没有化霜的功能我还不知道呢,是自动化霜吗?什么时间比较合适,每次要多长时间呢?板子上只做了一个继电器,放在盒子里。化霜功能要是没有多大必要的话,我就不改板子了。盒子里没空间。
【6楼】 rober :自已DIY乐趣之一呢。想当时我的家人夸我的神态,再苦再累也值得 !呵呵.
再次谢谢各位,有什么不同的想法,请跟贴。 我也有兴趣做个玩玩
不指导使用NTC是否合适。公司正好有常温20度5K电NTC,不知道用到冰箱上是否合适 不指导使用NTC是否合适。公司正好有常温20度5K电NTC,不知道用到冰箱上是否合适
ntc不行哦! /*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;
} http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_306934.JPG
(原文件名:photo0170.JPG) 不错的资料,收下了 图片来了,先上图给各位看一下,软件还没来的及去写。
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) 楼主用的这个程序实际能够运行了吗,还有就是这个控制压缩机不行吧,会挂掉的,
页:
[1]