This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| et:examples:sensor:ntc [2009/08/17 19:51] – raivo.sell | et:examples:sensor:ntc [2009/11/05 13:30] (current) – eemaldatud mikk.leini | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ===== Temperatuuri andur ===== | ||
| - | |||
| - | Temperatuuri andurina on [[et: | ||
| - | Termistor on valmistatud pooljuhtmaterjalidest, | ||
| - | {{: | ||
| - | Anduri moodul on varustatud 10 KΩ nimitakistusega termistoriga, | ||
| - | |||
| - | MS Exceli fail, mis võimaldab lihtsalt arvutada termistori väärtusi ka karakteristikut. | ||
| - | {{examples: | ||
| - | |||
| - | Sõltuvalt termistorist ja tema parameetritest on koefitsiendid erinevad. | ||
| - | Samuti tuleb tähelepanu pöörata pingejaguri takisti väärtustele ja ühendusskeemile. [[et: | ||
| - | |||
| - | Temperatuuri andur on plaadil ühendatud ühelt poolt toitega +5V ja teiselt polt porti PF2. | ||
| - | |||
| - | {{: | ||
| - | |||
| - | |||
| - | ===== Näide temrmistori analoog sisendi väärtuse saamiseks ===== | ||
| - | |||
| - | < | ||
| - | /* Lihtne AD muunduri kasutamine | ||
| - | Raivo Sell (2009) | ||
| - | */ | ||
| - | #include < | ||
| - | |||
| - | int main(void) { | ||
| - | |||
| - | unsigned int ntc; // analoog-digitaal muunduri lugem | ||
| - | ADMUX = 0xC0; | ||
| - | |||
| - | while(1) { | ||
| - | ADCSRA = 0xC3; | ||
| - | while ( ADCSRA & (1<< | ||
| - | // oodatakse kuni konverteerimine on lõpetatud | ||
| - | ntc = ADC; | ||
| - | } | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | ===== Näide Temperatuuri kuvamisest LCD-le ===== | ||
| - | |||
| - | Kasutatud on LCD ja Pinops teeke. Temperatuuri ja ADC näitude tabel pärineb NTC Exceli tabelist. | ||
| - | |||
| - | <code c> | ||
| - | // Antud kood kuvab LCD-l ADC väärtuse ja temperatuuri | ||
| - | |||
| - | #define RREF 10000 // termistori nimitakistus 25 kraadi juures | ||
| - | #define BVALUE 3977 // B väärtus termistori andmelehelt | ||
| - | |||
| - | #include < | ||
| - | #include < | ||
| - | #include < | ||
| - | #include < | ||
| - | #include < | ||
| - | #include " | ||
| - | #include " | ||
| - | |||
| - | // Positive Celcius temperatures (ADC-value) | ||
| - | // from -10 to 100 degrees | ||
| - | // Do not let |TEMP_MIN| + |TEMP_MAX| be greater than 127 (because of 8 bit variables) | ||
| - | const int8_t | ||
| - | const int8_t | ||
| - | const uint16_t TEMP_TABLE[] PROGMEM = | ||
| - | { | ||
| - | 542, | ||
| - | 722, | ||
| - | 843, | ||
| - | 916, | ||
| - | 958, | ||
| - | 983, | ||
| - | 997, | ||
| - | }; | ||
| - | |||
| - | // | ||
| - | // ADC conversion waiting | ||
| - | // | ||
| - | void adc_wait_until_done(void) | ||
| - | { | ||
| - | while (IS_BIT_SET(ADCSRA, | ||
| - | { | ||
| - | asm volatile (" | ||
| - | } | ||
| - | } | ||
| - | |||
| - | // | ||
| - | // 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 (+5V) | ||
| - | ADMUX |= BIT(REFS0); | ||
| - | |||
| - | // Take test sample to "warm up" converter | ||
| - | // Usually the first sample is discarded | ||
| - | SET_BIT(ADCSRA, | ||
| - | adc_wait_until_done(); | ||
| - | |||
| - | // Real sampling, sum up specifed number of samples | ||
| - | for (unsigned char i = 0; i < num_samples; | ||
| - | { | ||
| - | SET_BIT(ADCSRA, | ||
| - | adc_wait_until_done(); | ||
| - | |||
| - | // Sum-up | ||
| - | result += ADCW; | ||
| - | } | ||
| - | |||
| - | // De-activate ADC | ||
| - | CLEAR_BIT(ADCSRA, | ||
| - | |||
| - | // Return averaged result | ||
| - | return (result / num_samples); | ||
| - | } | ||
| - | |||
| - | // | ||
| - | // Main program | ||
| - | // | ||
| - | int main (void) | ||
| - | { | ||
| - | char buffer[8]; | ||
| - | int8_t cel; | ||
| - | uint16_t volt; | ||
| - | |||
| - | // Init display | ||
| - | lcd_init(LCD_DISP_ON); | ||
| - | |||
| - | // Endless loop | ||
| - | while (1) | ||
| - | { | ||
| - | // Sample voltage | ||
| - | volt = adc_sample_value(2, | ||
| - | |||
| - | // Get celsius temperature from table | ||
| - | for (cel = TEMP_MAX - TEMP_MIN; cel > 0; cel--) | ||
| - | { | ||
| - | if (volt > pgm_read_word(& | ||
| - | } | ||
| - | |||
| - | // Normalize | ||
| - | cel += TEMP_MIN; | ||
| - | |||
| - | // Output results | ||
| - | lcd_clrscr(); | ||
| - | |||
| - | // ADC value | ||
| - | itoa(volt, | ||
| - | lcd_gotoxy(0, | ||
| - | lcd_puts(" | ||
| - | lcd_puts(buffer); | ||
| - | |||
| - | // Temperature | ||
| - | itoa(cel, buffer, 10); | ||
| - | lcd_gotoxy(0, | ||
| - | lcd_puts(" | ||
| - | lcd_puts(buffer); | ||
| - | |||
| - | // Wait for 500 milliseconds | ||
| - | _delay_ms(500); | ||
| - | } | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | ===== Automaatse mõõtepiirkonnaga mõõtmine ===== | ||
| - | |||
| - | 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. | ||
| - | |||
| - | <code c> | ||
| - | // | ||
| - | // ADC sampling and integrating in automatic measuring region | ||
| - | // | ||
| - | // Mikk Leini | ||
| - | // | ||
| - | // 2009 | ||
| - | // | ||
| - | |||
| - | // Include avrlibc | ||
| - | #include < | ||
| - | #include < | ||
| - | |||
| - | // Include common library | ||
| - | #include " | ||
| - | |||
| - | // Math operations | ||
| - | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | ||
| - | #define MAX(a, b) ((a) > (b) ? (a) : (b)) | ||
| - | #define INTEGRATE(value, | ||
| - | |||
| - | // Configure pins | ||
| - | #define SEGMENT_DISPLAY_LATCH | ||
| - | #define SEGMENT_DISPLAY_DATA_OUT | ||
| - | #define SEGMENT_DISPLAY_CLOCK | ||
| - | |||
| - | // | ||
| - | // 7 segment display initialization | ||
| - | // | ||
| - | void segment_diplay_init(void) | ||
| - | { | ||
| - | // Set latch, data out and clock pins as output | ||
| - | pin_setup_output(SEGMENT_DISPLAY_LATCH); | ||
| - | pin_setup_output(SEGMENT_DISPLAY_DATA_OUT); | ||
| - | pin_setup_output(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; // " | ||
| - | case 2 : map = 0b01011011; break; // " | ||
| - | case 3 : map = 0b01001111; break; // " | ||
| - | 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; | ||
| - | } | ||
| - | |||
| - | // Latch low | ||
| - | pin_clear(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 | ||
| - | pin_set_to(SEGMENT_DISPLAY_DATA_OUT, | ||
| - | |||
| - | // Clock high for certain period | ||
| - | pin_set(SEGMENT_DISPLAY_CLOCK) | ||
| - | _delay_us(1); | ||
| - | |||
| - | // Clock low for certain period | ||
| - | pin_clear(SEGMENT_DISPLAY_CLOCK) | ||
| - | _delay_us(1); | ||
| - | } | ||
| - | |||
| - | // Latch high | ||
| - | pin_set(SEGMENT_DISPLAY_LATCH); | ||
| - | } | ||
| - | |||
| - | // | ||
| - | // ADC conversion waiting | ||
| - | // | ||
| - | void adc_wait_until_done(void) | ||
| - | { | ||
| - | while (IS_BIT_SET(ADCSRA, | ||
| - | { | ||
| - | asm volatile (" | ||
| - | } | ||
| - | } | ||
| - | |||
| - | // | ||
| - | // 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, | ||
| - | adc_wait_until_done(); | ||
| - | |||
| - | // Real sampling, sum up specifed number of samples | ||
| - | for (unsigned char i = 0; i < num_samples; | ||
| - | { | ||
| - | SET_BIT(ADCSRA, | ||
| - | adc_wait_until_done(); | ||
| - | |||
| - | // Sum-up | ||
| - | result += ADCW; | ||
| - | } | ||
| - | |||
| - | // De-activate ADC | ||
| - | CLEAR_BIT(ADCSRA, | ||
| - | |||
| - | // Return averaged result | ||
| - | return (result / num_samples); | ||
| - | } | ||
| - | |||
| - | // | ||
| - | // Program entrance function | ||
| - | // | ||
| - | int main(void) | ||
| - | { | ||
| - | unsigned short lowValue | ||
| - | 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, | ||
| - | |||
| - | // Endless loop | ||
| - | while (1) | ||
| - | { | ||
| - | // Sample ADC channel 2 four times | ||
| - | // Integrate value over 25 steps (50 ms each) | ||
| - | INTEGRATE(value, | ||
| - | |||
| - | // Check for new lower limit | ||
| - | lowValue = MIN(lowValue, | ||
| - | |||
| - | // Check for new higher limit | ||
| - | highValue = MAX(highValue, | ||
| - | |||
| - | // 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); | ||
| - | } | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | ===== Viited ===== | ||
| - | |||
| - | * [[http:// | ||