(原文件名:D__资料_电子_利用PIC_MCU中的CTMU _二极管_1N4148测量温度_00006.png)
点击此处下载 ourdev_545583.PDF(文件大小:342K) (原文件名:利用PIC_MCU中的CTMU _二极管_1N4148测量温度.PDF)
点击此处下载 ourdev_545584.PDF(文件大小:337K) (原文件名:充电时间测量单元CTMU.PDF)作者: millwood0 时间: 2010-4-12 03:18
what the datasheet engineer didn't tell you is that the diversity between two devices of identical type (one 1n4148 vs. another 1n4148 for example) would be so great that you will have to calibrate each device - making this approach less practical.作者: kangar0065 时间: 2010-4-12 03:27
回复【1楼】millwood0
what the datasheet engineer didn't tell you is that the diversity between two devices of identical type (one 1n4148 vs. another 1n4148 for example) would be so great that you will have to calibrate each device - making this approach less practical.
-----------------------------------------------------------------------
确实存在一个校准的问题,我在坛子上搜索过以前用过这个东西的前辈,他们都说稳定度和线性不错,甚至优于热敏电阻.
而且他们没有使用恒流源供电,还存在着一个电压调制的问题.这个单片机IO内部有恒流源.有一点略微的优势吧作者: millwood0 时间: 2010-4-12 04:46
you can use an external ccs (a jfet for example), or an external voltage regulator, or an inter Vref to power the diode.
the voltage sensitivity is basic physics and it is very linear.作者: eduhf_123 时间: 2010-4-12 06:03
MARK PN结测温作者: master5888 时间: 2010-4-12 08:13
luguo作者: fsclub 时间: 2010-4-12 08:15
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3320979&bbs_page_no=1&search_mode=3&search_text=fsclub&bbs_id=9999作者: kangar0065 时间: 2010-4-12 11:41
回复【3楼】millwood0
you can use an external ccs (a jfet for example), or an external voltage regulator, or an inter Vref to power the diode.
the voltage sensitivity is basic physics and it is very linear.
-----------------------------------------------------------------------
可以说的更详细些吗?好像没有相关的资料作者: fw190d9 时间: 2010-4-13 06:50
不如来个18B20实在。4148等就没有离散性了,做这样的AD不如直接来个NTC。作者: kangar0065 时间: 2010-4-20 09:13
4148便宜啊作者: portx 时间: 2010-4-20 09:20
关注,不知道精度能到多少,全温度范围的线性度如何,后期的数据是否需要进行多次方拟合作者: oxalis 时间: 2010-4-27 20:53
关注
谁来做个试试?作者: zhihaoa 时间: 2010-6-5 08:38
想法儿不错,作来试试作者: heyuncun 时间: 2010-6-5 11:29
mark作者: gxy508 时间: 2010-6-5 12:11
mark作者: millwood0 时间: 2010-6-5 23:18
I can post my code later if anyone wants it.
the issue with this approach is that you have to be able to find a low-tempco reference voltage (like a bandgap ref). Otherwise, you have to use Vdd, and with a typical 10bit adc, your minimum resolution is 5mv, which is about 2 - 3 degrees.
not to mention calibration issues.
if you use a temperature compensated tl431-type regulator, you can get better precision.作者: kangar0065 时间: 2010-6-6 21:13
静等下文作者: rqiang 时间: 2010-6-6 21:42
在要求不高的产品中试可以使用的。作者: frogrider 时间: 2010-6-6 22:30
mark作者: elec2000 时间: 2010-6-6 22:59
PN结的温度/电压的线性度非常好,但是个体之间的一致性不好,即互换性不好作者: millwood0 时间: 2010-6-7 00:13
here is the code.
unsigned long random_vN(void) { //using von Neumann middle square approach to return a random number
static unsigned long seed=5634; //3021, 3421
seed=((seed*seed) & 0x00ffff00) >> 8;
return seed;
}
void adc_init(void) { //initialize the adc
// ADCON0 = config_mask;
ADCS2=0, ADCS1=1, ADCS0=0; //adc running at fosc/32
ADFM=1; //adc results right justified
VCFG=1; //Vref on porta2/an2
ADON=0; //adc off
}
unsigned int adc_read(unsigned char ch){//read adc
ADON=1; //turn on the adc
// ANSEL |= ch; //select the adc channel, and adc at fosc/32
// TRISIO |= ch; //turn it as input
// CHS1=(ch-1) >> 1; //select the channel
// CHS0=(ch-1);
switch (ch) {
case AN0: CHS2=0, CHS1=0, CHS0=0, ANSEL=AN0; break;
case AN2: CHS2=0, CHS1=1, CHS0=0, ANSEL=AN2; break;
default: NOP(); NOP(); NOP(); NOP(); NOP(); break;
}
// delay_us(1); //turn on the adc
// may need some delays here
Tacq_delay(); //delay for tacq
GODONE=1; //start the adc
while (GODONE) continue; //wait for the adc to complete;
ADON=0; //turn off the adc
return (ADRESH<<8) + ADRESL;
// return random_vN() & 0x3ff; //return a random 10bit number, for testing purposes
}
void ltoa(char *s, signed long ul, unsigned char length) { //convert unsigned long to a string, 3 dps
unsigned char i;
if (ul<0) {
ul=-ul;
*s++='-';
} else *s++='+';
i=length;
do {
// if (i==(length-3)) s[i--]='.';
s[i--]=ul % 10 + '0';
ul = ul / 10;
} while (ul);
}
void mcu_init(void) {
CMCON0=0x07; //turn off comparators;
//TRISIO=0b11; //input on GPIO0, all others digital output;
ANSEL=0x00; //all ports gpio
IRCF2=1, IRCF1=1, IRCF0=0; //4Mhz
}
void main(void)
{
//unsigned char temp=0, gSPad[9], i;
unsigned int i, tmp, tmp2;
//unsigned int val_L, val_R;
mcu_init(); //initialize the mcu
lcd_init(); //initialize the lcd
adc_init(); //initialize the adc
strcpy(vRAM, str_0); lcd_display(LCD_Line0, vRAM);
strcpy(vRAM, str_v); lcd_display(LCD_Line1, vRAM); delay_ms(50);
strcpy(vRAM, str_adcx); lcd_display(LCD_Line_ADCX, vRAM);
strcpy(vRAM, str_tempC); lcd_display(LCD_Line_Temp, vRAM);
// sleep();
while (1){
//TODO Auto-generated main function
i=adc_read(ADC_CH0);
// strcpy(vRAM, str_adcx); ltoa(&vRAM[5], i, 7); lcd_display(LCD_Line_ADCX, vRAM);
// the following is for calibration purposes
strcpy(vRAM, str_volt); ltoa(&vRAM[5], adc2_uv(i), 7); lcd_display(LCD_Line_ADCX, vRAM);
// the following is for actual displaying, in 1/100th of C. so 4568C means 45.68C; -423C means -4.23C
strcpy(vRAM, str_tempC); ltoa(&vRAM[5], uv2_tempC(adc2_uv(i)), 7); lcd_display(LCD_Line_Temp, vRAM);
delay_ms(DLY_main_loop); //delay some time
}
}
=============end of code====================
you will need to do a few things to make it work.
1) specify Vref. now, it is specified at 2v. it should be whatever your vref source is.作者: millwood0 时间: 2010-6-7 00:14
2) caliberation: you should compile the code, and caliberate it at two temperatures: T0 and T1, both in C. I chose 0C (using ice and water mixture), and 100C (boiling water). Put the diode(s) into T0/T1, and see what the voltage reading is and put it into the code and recompile the code.
then you are done.
improvement opportunities:
1) the display of temperature is in 0.01C, but without the decimal point. you can rewrite the ltoa() to mitigate that.
2) you can also add multiple channels to it.
I will post the schmeatic later.作者: millwood0 时间: 2010-6-7 01:23
the connection is as follows:
1) the code samples the voltage on RA0/AN0 - which is user-configuration. and it can be AN0/AN2 (already implemented. AN1 is used as the reference voltage. you can expand it to other adc-pins). if you set it up that way, you can sample multiple diodes, and read temperatures as multiple places. However, you have to change the caliberation to make that work.
2) you can use as many diodes in serial as you can, as long as the the total forward drop is less than Vref.
3) the diodes can be powered by a CCS but a resistor will do as well.
I will post the schematic later.作者: hecat 时间: 2010-6-7 03:11
MARK。作者: millwood0 时间: 2010-6-7 07:57
here is the schematic: essentially a diode or a series of diodes powered by a current source.
the current source can be a jfet, or resistor (though psrr suffers).
now, only one sensor is sampled, on AN0. but you can easily change the code to sample more.
(原文件名:16F684 temp diode.PNG)作者: millwood0 时间: 2010-6-7 08:05
here is the revised code: changed ltoa() to incorporate decimal points.
unsigned long random_vN(void) { //using von Neumann middle square approach to return a random number
static unsigned long seed=5634; //3021, 3421
seed=((seed*seed) & 0x00ffff00) >> 8;
return seed;
}
void adc_init(void) { //initialize the adc
// ADCON0 = config_mask;
ADCS2=0, ADCS1=1, ADCS0=0; //adc running at fosc/32
ADFM=1; //adc results right justified
VCFG=1; //Vref on porta2/an2
ADON=0; //adc off
}
unsigned int adc_read(unsigned char ch){//read adc
ADON=1; //turn on the adc
// ANSEL |= ch; //select the adc channel, and adc at fosc/32
// TRISIO |= ch; //turn it as input
// CHS1=(ch-1) >> 1; //select the channel
// CHS0=(ch-1);
switch (ch) {
case AN0: CHS2=0, CHS1=0, CHS0=0, ANSEL=AN0; break;
case AN2: CHS2=0, CHS1=1, CHS0=0, ANSEL=AN2; break;
default: NOP(); NOP(); NOP(); NOP(); NOP(); break;
}
// delay_us(1); //turn on the adc
// may need some delays here
Tacq_delay(); //delay for tacq
GODONE=1; //start the adc
while (GODONE) continue; //wait for the adc to complete;
ADON=0; //turn off the adc
return (ADRESH<<8) + ADRESL;
// return random_vN() & 0x3ff; //return a random 10bit number, for testing purposes
}
void ltoa(char *s, signed long ul, unsigned char length, unsigned char dp) { //convert unsigned long to a string, 3 dps
unsigned char i;
char sign=0; //no sign
i=length;
do {
if (i==(length-dp)) s[i--]='.';
s[i--]=ul % 10 + '0';
ul = ul / 10;
} while (ul);
switch (sign) {
case -1: s='-'; break;
case +1: s='+'; break;
}
}
void mcu_init(void) {
CMCON0=0x07; //turn off comparators;
//TRISIO=0b11; //input on GPIO0, all others digital output;
ANSEL=0x00; //all ports gpio
IRCF2=1, IRCF1=1, IRCF0=0; //4Mhz
}
void main(void)
{
//unsigned char temp=0, gSPad[9], i;
unsigned int i, tmp, tmp2;
//unsigned int val_L, val_R;
mcu_init(); //initialize the mcu
lcd_init(); //initialize the lcd
adc_init(); //initialize the adc
strcpy(vRAM, str_0); lcd_display(LCD_Line0, vRAM);
strcpy(vRAM, str_v); lcd_display(LCD_Line1, vRAM); delay_ms(50);
strcpy(vRAM, str_adcx); lcd_display(LCD_Line_ADCX, vRAM);
strcpy(vRAM, str_tempC); lcd_display(LCD_Line_Temp, vRAM);
// sleep();
while (1){
//TODO Auto-generated main function
i=adc_read(ADC_CH0);
// strcpy(vRAM, str_adcx); ltoa(&vRAM[5], i, 7); lcd_display(LCD_Line_ADCX, vRAM);
// the following is for calibration purposes
strcpy(vRAM, str_volt); ltoa(&vRAM[5], adc2_uv(i)/100, 8,1); lcd_display(LCD_Line_ADCX, vRAM);
// the following is for actual displaying, in 1/100th of C. so 4568C means 45.68C; -423C means -4.23C
strcpy(vRAM, str_tempC); ltoa(&vRAM[5], uv2_tempC(adc2_uv(i)), 8,2); lcd_display(LCD_Line_Temp, vRAM);
delay_ms(DLY_main_loop); //delay some time
}
}
==========================
here is the display.
(原文件名:16F684 temp diode v2.PNG)作者: millwood0 时间: 2010-6-7 08:11
the calibration here is that 699.2mv=0C, and 750mv=100C - I had it backwards, :).
close enough, :) - the error is due to rounding.作者: exploer 时间: 2010-6-7 08:40
回复【26楼】millwood0
-----------------------------------------------------------------------
英文好的高手。作者: jacky1982512 时间: 2010-6-7 09:12
回复【1楼】millwood0
-----------------------------------------------------------------------