This is an old revision of the document!
MS Exceli fail, mis võimaldab lihtsalt arvutada termistori väärtusi ka karakteristikut. ntc.xls
Sõltuvalt termistorist ja tema parameetritest on koefitsiendid erinevad. Samuti tuleb tähelepanu pöörata pingejaguri takisti väärtustele ja ühendusskeemile.
// Antud kood kuvab LCD-l ADC väärtuse, analoog pinge, loenduri ja temperatuuri #define RREF 10000 // termistori nimitakistus 25 kraadi juures #define BVALUE 3977 // B väärtus termistori andmelehelt #include <avr\io.h> #include <inttypes.h> #include <util\delay.h> #include "lcd.c" #define SET(x) |= (1<<x) //defineeritakse kõrge bit pordis x #define CLR(x) &=~(1<<x) //defineeritakse madal bit pordis x #define INV(x) ^=(1<<x) //defineeritakse biti inverteerimine pordis x #define bit_get(p,m) ((p) & (m)) //returns 1 if bit is set, otherwise returns 0 #define BIT(x) (0x01 << (x)) #define MAX(a, b) ((a) > (b)) ? (a):(b) unsigned char echo[10]; unsigned int ntc=0; unsigned int adc=0; unsigned int num=0; const int TEMP_pos[] PROGMEM = // Positive Celcius temperatures (ADC-value) { // from 0 to 60 degrees 806,796,786,775,765,754,743,732,720,709,697,685,673,661,649, 636,624,611,599,586,574,562,549,537,524,512,500,488,476,464, 452,440,429,418,406,396,385,374,364,354,344,334,324,315,306, 297,288,279,271,263,255,247,240,233,225,219,212,205,199,193, 187, }; int TEMP_neg[] = // Negative Celcius temperatures (ADC-value) { // from -1 to -15 degrees 815,825,834,843,851,860,868,876,883,891,898,904,911,917,923, }; void init_lcd(void){ // initialize display, cursor off lcd_init(LCD_DISP_ON); lcd_clrscr(); } void write_echo(void){ lcd_clrscr (); itoa(num,echo,10); lcd_gotoxy(8,0); lcd_puts(echo); itoa(ntc,echo,10); lcd_gotoxy(8,1); // pos 0 row 2 lcd_puts(echo); // write ID-number } void lcd(int arv,int pos, int rida){ itoa(arv,echo,10); lcd_gotoxy(pos,rida); lcd_puts(echo); } void temp_read(){ int ADCresult = 0; int i=0; ADCresult = ADC_read(2); // Find the ADC value adc=ADCresult; for (i=0;i<=100;i++){ if (ADCresult > pgm_read_word(&TEMP_pos[i])){break;} } ntc=i; } int main (void) { char buffer[7]; uint16_t volt; init_lcd(); //init_ports(); while(1) { //ntc=ADC_read(2); temp_read(); num++; lcd(ntc,0,0); lcd(adc,0,1); volt=50*adc/1023; lcd(volt,10,1); lcd(num,10,0); _delay_ms(500); // wait 50 millisec lcd_clrscr (); //write_echo(); } }
Et ühe numbri-indikaatoriga adekvaatseid väärtusi kuvada, võib kasutusele võtta automaatse mõõtepiirkonna. See tähendab, et programm peab pidevalt arvet minimaalse ja maksimaalse mõõdetud väärtuse üle ja number mis kuvatakse näitab mõõdetud väärtuse suhtarvu minimaalsest maksimaalseni skaalas 0 kuni 9. Näiteks termomeetri näitu mõõtes saab anduri panna külma vette (0 kraadi) ning keevasse vette (100 kraadi) ja kui siis 0-st 100-kraadini mõõtmisi teha, kuvatakse indikaatoril näite kümnete kraadide kaupa.
// // ADC sampling and integrating in automatic measuring region // // Mikk Leini // // 2009 // // Include avrlibc #include <avr/io.h> #include <util/delay.h> // Include common library #include "pinops.h" // Math operations #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define INTEGRATE(value, new_value, n) value = (value * (n - 1) + new_value) / n; // Configure pins #define SEGMENT_DISPLAY_LATCH PORTPIN(G, 2) #define SEGMENT_DISPLAY_DATA_OUT PORTPIN(C, 6) #define SEGMENT_DISPLAY_CLOCK PORTPIN(C, 7) // // 7 segment display initialization // void segment_diplay_init(void) { // Set latch, data out and clock pins as output setup_output_pin(SEGMENT_DISPLAY_LATCH); setup_output_pin(SEGMENT_DISPLAY_DATA_OUT); setup_output_pin(SEGMENT_DISPLAY_CLOCK); } // // Digit writing to 7 segment display // void segment_display_write(unsigned char digit) { unsigned char map; // Decimal to segment map switch (digit) { case 0 : map = 0b00111111; break; // Every bit corresponds to one segment case 1 : map = 0b00000110; break; // "1" case 2 : map = 0b01011011; break; // "2" case 3 : map = 0b01001111; break; // "3" and so on case 4 : map = 0b01100110; break; case 5 : map = 0b01101101; break; case 6 : map = 0b01111100; break; case 7 : map = 0b00000111; break; case 8 : map = 0b01111111; break; case 9 : map = 0b01100111; break; default: map = 0b01111001; // E like Error } // Latch low clear_pin(SEGMENT_DISPLAY_LATCH); // Send every bit in the byte. MSB (most significant bit) first. for (signed char i = 7; i >= 0; i--) { // If bit is set, sets the data out pin, otherwise not set_pin_to(SEGMENT_DISPLAY_DATA_OUT, IS_BIT_SET(map, i)); // Clock high for certain period set_pin(SEGMENT_DISPLAY_CLOCK) _delay_us(1); // Clock low for certain period clear_pin(SEGMENT_DISPLAY_CLOCK) _delay_us(1); } // Latch high set_pin(SEGMENT_DISPLAY_LATCH); } // // ADC conversion waiting // void adc_wait_until_done(void) { while (IS_BIT_SET(ADCSRA, ADSC)) { asm volatile ("nop"); } } // // ADC channel value sampling // unsigned short adc_sample_value(unsigned char channel, unsigned char num_samples) { unsigned short result = 0; // ADC setup - prescaler 8 ADCSRA = BIT(ADEN) | BIT(ADPS1) | BIT(ADPS0); // Specify channel ADMUX = channel & 0x0F; // Reference voltage to external ADMUX |= BIT(REFS0); // Take test sample to "warm up" converter // Usually the first sample is discarded SET_BIT(ADCSRA, ADSC); adc_wait_until_done(); // Real sampling, sum up specifed number of samples for (unsigned char i = 0; i < num_samples;i++) { SET_BIT(ADCSRA, ADSC); adc_wait_until_done(); // Sum-up result += ADCW; } // De-activate ADC CLEAR_BIT(ADCSRA, ADEN); // Return averaged result return (result / num_samples); } // // Program entrance function // int main(void) { unsigned short lowValue = 0xFFFF; unsigned short highValue = 0x0000; unsigned short value; unsigned char relativeValue; // 7 segment display initialization segment_diplay_init(); // To not get wrong lowValue we should set get the initial integrated value value = adc_sample_value(2, 4); // Endless loop while (1) { // Sample ADC channel 2 four times // Integrate value over 25 steps (50 ms each) INTEGRATE(value, adc_sample_value(2, 4), 25); // Check for new lower limit lowValue = MIN(lowValue, value); // Check for new higher limit highValue = MAX(highValue, value); // Calculate relative value // Range from lowValue to highValue is converted to 0 to 9 relativeValue = 9 * (value - lowValue) / (highValue - lowValue); // Write digit segment_display_write(relativeValue); // Wait 50 ms _delay_ms(50); } }