二极管4148 三极管9013 PN结温度测量
看到想做一个孵小鸡的装置,让孩子孵一只小鸡出来,应该用什么样的加热器件,请指教。
里面提到了二极管的温度测量
上网找了一下原理.张贴如下
http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_545578.png
(原文件名:D__资料_电子_利用PIC_MCU中的CTMU _二极管_1N4148测量温度.png)
http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_545579.png
(原文件名:D__资料_电子_利用PIC_MCU中的CTMU _二极管_1N4148测量温度_00002.png)
http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_545580.png
(原文件名:D__资料_电子_利用PIC_MCU中的CTMU _二极管_1N4148测量温度_00003.png)
http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_545581.png
(原文件名:D__资料_电子_利用PIC_MCU中的CTMU _二极管_1N4148测量温度_00005.png)
http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_545582.png
(原文件名:D__资料_电子_利用PIC_MCU中的CTMU _二极管_1N4148测量温度_00006.png)
点击此处下载 ourdev_545583.PDF(文件大小:342K) (原文件名:利用PIC_MCU中的CTMU _二极管_1N4148测量温度.PDF)
点击此处下载 ourdev_545584.PDF(文件大小:337K) (原文件名:充电时间测量单元CTMU.PDF) 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. 回复【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内部有恒流源.有一点略微的优势吧 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. MARK PN结测温 luguo http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3320979&bbs_page_no=1&search_mode=3&search_text=fsclub&bbs_id=9999 回复【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.
-----------------------------------------------------------------------
可以说的更详细些吗?好像没有相关的资料 不如来个18B20实在。4148等就没有离散性了,做这样的AD不如直接来个NTC。 4148便宜啊 关注,不知道精度能到多少,全温度范围的线性度如何,后期的数据是否需要进行多次方拟合 关注
谁来做个试试? 想法儿不错,作来试试 mark mark 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. 静等下文 在要求不高的产品中试可以使用的。 mark PN结的温度/电压的线性度非常好,但是个体之间的一致性不好,即互换性不好 here is the code.
============16f684 diode temp measurement================
#include <htc.h>
#include <string.h>
#include "delay.h"
//#include "lcd_4bit.h"
#include "lcd_3wi.h"
__CONFIG(MCLRDIS & BORDIS & WDTDIS & PWRTEN & INTIO);
#define sleep() asm("sleep") //put the mcu to sleep
#define AN0 (1<<0) //an0
#define AN2 (1<<2) //an2 - an1 used a vref in this application
#define ADC_CH0 AN0 //adc on an0
#define ADC_CH1 AN2 //adc on an2
#define LCD_Line_ADCX LCD_Line0 //L ch on lcd_line0
#define LCD_Line_Temp LCD_Line1 //R ch on lcd_line1
#define LED_PIN (1<<5) //led on GPIO1
#define PA_SET(bits) PORTA |= (bits); //set bits on porta
#define PA_CLR(bits) PORTA &=~(bits); //clear bits on porta
#define PA_FLP(bits) PORTA ^= (bits); //flip bits on porta
#define DLY_main_loop 300 //main loop delay, in ms
#define Vref 2000000ul //reference voltage, in uv. Vref=2v
#define adc2_uv(adc_int) ((signed long) (Vref*((unsigned long)adc_int))>>10) //convert 10 bits to uv. so 1000 = 1mv.
//caliberation temperatures
#define T1 0l //1st caliberation temperature, in 0.01C
#define adc_uv_at_T1 699218l //adc reading, in uv, at T1
#define T2 10000l //2nd caliberation temperature, in 0.01C
#define adc_uv_at_T2 750000l //adc reading, in uv, at T2
#define uv2_tempC(uv) T1+(signed long) (T2-T1)*((uv)-adc_uv_at_T1)/(adc_uv_at_T2-adc_uv_at_T1) //convert uv to C. 2 decimal points
#define Tacq_delay() NOP(); NOP(); NOP(); NOP(); NOP(); NOP() //delay for tacq
const unsigned char str_adcx[] ="ADC : ";
const unsigned char str_volt[] ="Volt: uv";
const unsigned char str_tempC[]="Temp: C";
const unsigned char str_0[]="16F684 TempMeter";
const unsigned char str_v[]="version 0.2-1234";
unsigned char vRAM;
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='.';
s=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, 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, i, 7); lcd_display(LCD_Line_ADCX, vRAM);
// the following is for calibration purposes
strcpy(vRAM, str_volt); ltoa(&vRAM, 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, 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. 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. 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. MARK。 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.
http://cache.amobbs.com/bbs_upload782111/files_29/ourdev_560067YO6R47.PNG
(原文件名:16F684 temp diode.PNG) here is the revised code: changed ltoa() to incorporate decimal points.
======code==========
#include <htc.h>
#include <string.h>
#include "delay.h"
//#include "lcd_4bit.h"
#include "lcd_3wi.h"
__CONFIG(MCLRDIS & BORDIS & WDTDIS & PWRTEN & INTIO);
#define sleep() asm("sleep") //put the mcu to sleep
#define AN0 (1<<0) //an0
#define AN2 (1<<2) //an2 - an1 used a vref in this application
#define ADC_CH0 AN0 //adc on an0
#define ADC_CH1 AN2 //adc on an2
#define LCD_Line_ADCX LCD_Line0 //L ch on lcd_line0
#define LCD_Line_Temp LCD_Line1 //R ch on lcd_line1
#define LED_PIN (1<<5) //led on GPIO1
#define PA_SET(bits) PORTA |= (bits); //set bits on porta
#define PA_CLR(bits) PORTA &=~(bits); //clear bits on porta
#define PA_FLP(bits) PORTA ^= (bits); //flip bits on porta
#define DLY_main_loop 300 //main loop delay, in ms
#define Vref 2000000ul //reference voltage, in uv. Vref=2v
#define adc2_uv(adc_int) ((signed long) (Vref*((unsigned long)adc_int))>>10) //convert 10 bits to uv. so 1000 = 1mv.
//caliberation temperatures
#define T1 0l //1st caliberation temperature, in 0.01C
#define adc_uv_at_T1 699218l //adc reading, in uv, at T1
#define T2 10000l //2nd caliberation temperature, in 0.01C
#define adc_uv_at_T2 750000l //adc reading, in uv, at T2
#define uv2_tempC(uv) T1+(signed long) (T2-T1)*((uv)-adc_uv_at_T1)/(adc_uv_at_T2-adc_uv_at_T1) //convert uv to C. 2 decimal points
#define Tacq_delay() NOP(); NOP(); NOP(); NOP(); NOP(); NOP() //delay for tacq
const unsigned char str_adcx[] ="ADC : ";
const unsigned char str_volt[] ="Volt: mv";
const unsigned char str_tempC[]="Temp: C";
const unsigned char str_0[]="16F684 TempMeter";
const unsigned char str_v[]="version 0.2-1234";
unsigned char vRAM;
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
if (ul<0) {
ul=-ul;
sign=-1; //negative sign
} else sign=+1; //positive sign
i=length;
do {
if (i==(length-dp)) s='.';
s=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, 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, i, 7); lcd_display(LCD_Line_ADCX, vRAM);
// the following is for calibration purposes
strcpy(vRAM, str_volt); ltoa(&vRAM, 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, 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.
http://cache.amobbs.com/bbs_upload782111/files_29/ourdev_560069HHOS9I.PNG
(原文件名:16F684 temp diode v2.PNG) the calibration here is that 699.2mv=0C, and 750mv=100C - I had it backwards, :).
so 675.7mv = -46.12. let's confirm it:
675.7mv -> 0C + (675.7-699.2)*(100C-0C)/(750mv-699.2mv)=-23.5mv*100/(50.8mv)=46.2mv.
close enough, :) - the error is due to rounding. 回复【26楼】millwood0
-----------------------------------------------------------------------
英文好的高手。 回复【1楼】millwood0
-----------------------------------------------------------------------
你装什么,总是用英语!有意思 在国外,没有中文输入法。。。 mark 不错呀。冲这个应该给条裤子。那个英文不好的你有两个选择:一个是把英语学好了来,第二个就是不要看。 回复【28楼】jacky1982512
回复【1楼】millwood0
-----------------------------------------------------------------------
你装什么,总是用英语!有意思
-----------------------------------------------------------------------
1楼老大本来就是说英文, 就如同你装什么呀,说汉语一样.
你不愿意可以不看,如同国外的datasheet一样,你可以只看中文的,没有人逼你看 mark 二极管 温度测量 mark 值得关注 mark 回复【28楼】jacky1982512
回复【1楼】millwood0
-----------------------------------------------------------------------
你装什么,总是用英语!有意思
-----------------------------------------------------------------------
你唯一的帖子中用单片机测量交流电压的程序里为什么也用了英语呢?
你在装什么呢?难道是如同你自己所说,装比?这就是你回帖的美德?
刚刚注册进来,既要求助,又不懂得尊重别人!少教! 二极管 温度测量, 好资料, mark mark MARK MARK 暖小鸡要找受精的蛋,这个问题好象比恒温难点:-P MARK 不错! 好资料,要收留。 我来把文件直接上传吧
Using the PIC MCU CTMU for Temperature Measurementourdev_589487R1IU5G.pdf(文件大小:342K) (原文件名:Using the PIC MCU CTMU for Temperature Measurement.pdf) 关注,要mark mark了,以后慢慢学习~ MARK!! 学习记号! mark,学习,以后能用到. MARK 曾今做过PN极测温的人飘过,线性非常好,但是一致性很差,量产的时候校正的问题没办法搞定,最终放弃,老实用了DS18B20~~ mark,PN结测温。 mark mark kangar0065 发表于 2010-6-7 17:32 static/image/common/back.gif
不错呀。冲这个应该给条裤子。那个英文不好的你有两个选择:一个是把英语学好了来,第二个就是不要看。 ...
很酷的帖子,请问楼主 你孩子孵小鸡成功了吗,现在该长大了吧{:lol:} {:loveliness:} not bad !!!
MARK MARK make !!!! STM32有CTMU单元么? 最近 在 找 基准 相关 信息 。
翻到 ST 的 LM336 ,应该是 很旧的设计了,官网 查不到 这个器件。
PN结温可以 用来 补偿 某些 电压基准的温漂 。
页:
[1]