This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| et:examples:sensor:reflectance_sensor [2023/10/16 20:37] – created heiko.pikner | et:examples:sensor:reflectance_sensor [2023/10/16 21:16] (current) – heiko.pikner | ||
|---|---|---|---|
| Line 9: | Line 9: | ||
| ===== Teooria ===== | ===== Teooria ===== | ||
| - | [{{ : | + | ToDo |
| - | + | ||
| - | Objekti kauguse mõõtmiseks on olemas triangulatsioonimeetodil töötavad optilised andurid. Levinuimad neist on firma Sharp poolt toodetavad infrapuna (inglise keeles // | + | |
| - | + | ||
| - | [{{ : | + | |
| - | + | ||
| - | Sharp-i kaugusandurite väljund on pöördvõrdeline - kauguse kasvades see väheneb ja järjest aeglasemalt. Täpne kauguse ja väljundi vaheline graafik on toodud andurite andmelehel. Anduritel on vastavalt tüübile ka mõõtepiirkond, | + | |
| ===== Praktika | ===== Praktika | ||
| - | [{{ : | + | < |
| + | <code c> | ||
| + | // Kodulabori QTR_RC jooneanduri näidisprogramm | ||
| + | // Peegeldumise mõõtmise funktsioon on blokeeruv | ||
| + | #include <stdio.h> | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| - | Kodulabori andurite komplektis on Sharp-i infrapuna kaugusmõõdik GP2Y0A21YK mõõtepiirkonnaga 10-80 cm. Anduri väljundpinge on kuni 3 V sõltuvalt mõõdetavast kaugusest. Anduri saab ühendada Kodulabori mooduli külge valitud analoogkanalisse. Eelnevate andurite harjutuste baasil saab lihtsalt teha programmi, mis mõõdab kaugusmõõdiku väljundpinget, kuid lisaks on selle harjutuse eesmärk veel pinge kauguseks teisendamise protsessi tutvustamine. | + | // Kodulabor III |
| + | pin pin_rc_in_1 = PIN(B, 2); | ||
| + | pin pin_rc_in_2 = PIN(B, 1); | ||
| + | pin pin_rc_in_3 = PIN(B, 0); | ||
| + | pin pin_rc_in_4 = PIN(A, 7); | ||
| - | GP2Y0A21YK andmelehel on toodud väljundpinge ja mõõdetud kauguse vahelise sõltuvuse graafik. See pole lineaarne, kuid väljundpinge ja kauguse pöördväärtuse graafik peaaegu juba on, ning sellest on suhteliselt lihtne leida valem pinge kauguseks teisendamiseks. Valemi leidmiseks tuleb sama graafiku punktid sisestada mõnda tabelarvutuse programmi ja nendest uuesti graafik luua. Tabelarvutusprogrammides on graafiku punktide põhjal võimalik arvutada automaatselt välja trendijoon. Järgnevalt on toodud GP2Y0A21YK väljundpinge ja kauguse korrigeeritud pöördväärtuse vahelise seose graafik koos lineaarse trendijoonega. Väljundpinge on valemi lihtsustamise nimel juba teisendatud 10-bitiseks +5 V võrdluspingega analoog-digitaalmuunduri väärtuseks. | + | unsigned short QTR_RC_measure(pin rc_in_pin) |
| + | { | ||
| + | if(_sys_freq == 2) | ||
| + | Homelab_clock_init(); | ||
| - | [{{ : | + | // Pin setup |
| + | pin_setup_output(rc_in_pin); | ||
| - | Nagu graafikult näha, kattub trendijoon | + | // Reset timer |
| + | TC_ClearOverflowFlag(&TCD1); | ||
| + | TC_Restart(&TCD1); | ||
| - | 1 / (d + k) = a ⋅ ADC + b | + | |
| + | // Top value 9000 (~270cm) | ||
| + | // with clock freq of F_CPU / 64 | ||
| + | TC_SetPeriod(& | ||
| + | TC1_ConfigClockSource( &TCD1, TC_CLKSEL_DIV1_gc); | ||
| - | kus | + | // Create trigger pulse |
| + | pin_set(rc_in_pin); | ||
| - | * d on kaugus sentimeetrites | + | // Wait ~10 us |
| - | * k on korrigeerimiskonstant | + | |
| - | * ADC on pinge digitaliseeritud väärtus | + | |
| - | * a on lineaarliige (väärtus tuleb trendijoone võrrandist) | + | |
| - | * b on vabaliige (väärtus tuleb trendijoone võrrandist) | + | |
| - | Valemist saab avaldada kauguse d: | + | // Reset timer |
| + | TC_SetCount(& | ||
| - | d = (1 / (a ⋅ ADC + B)) - k | + | |
| + | pin_setup_input(rc_in_pin); | ||
| - | Põhimõtteliselt saakski selle valemiga kauguse välja arvutada, kuid see eeldaks ujukoma-arvutusi, | + | while (pin_get_value(rc_in_pin)) |
| + | { | ||
| + | // Timeout ? | ||
| + | if (TC_GetOverflowFlag(& | ||
| + | { | ||
| + | return 0; | ||
| + | } | ||
| + | } | ||
| - | d = (1 / a) / (ADC + B / a) - k | + | // Convert time to distance: |
| - | + | // | |
| - | Viies valemisse korrigeerimiskonstandi väärtuse ja trendijoone võrrandist saadud lineaar- ja vabaliikme (saadud jooniselt), tuleb kauguse arvutamise valemiks: | + | |
| - | + | ||
| - | d = 5461 / (ADC - 17) - 2 | + | |
| - | + | ||
| - | See valem on arvutatav 16-bitiste täisarvudega ja täiesti jõukohane AVR-ile. Enne arvutamist tuleb aga veenduda, et ADC väärtus oleks üle 17, sest muidu tekib nulliga jagamine või negatiivne kaugus, mis on ebaloogiline. | + | |
| - | + | ||
| - | Järgnevalt on toodud Kodulabori teegis kirja pandud funktsioon ADC väärtuse sentimeetriteks teisendamise kohta. Lineaar- ja vabaliige ning korrigeerimiskonstant pole funktsiooni jäigalt sisse kirjutatud, vaid need antakse ette IR kaugusanduri parameetrite struktuuri objektiga. Hoides parameetreid eraldi konstandis, saab hiljem programmi lihtsalt lisada uusi IR kaugusandurite mudeleid. | + | |
| - | + | ||
| - | <code c> | + | |
| - | // IR kaugusanduri parameetrite struktuur | + | |
| - | typedef const struct | + | |
| - | { | + | |
| - | const signed short a; | + | |
| - | const signed short b; | + | |
| - | const signed short k; | + | |
| } | } | ||
| - | ir_distance_sensor; | ||
| - | // GP2Y0A21YK anduri parameetrite objekt | ||
| - | const ir_distance_sensor GP2Y0A21YK = { 5461, -17, 2 }; | ||
| - | |||
| - | // IR kaugusanduri ADC väärtuse sentimeetriteks teisendamine | ||
| - | // Tagastatakse -1, kui teisendus ei õnnestunud | ||
| - | signed short ir_distance_calculate_cm(ir_distance_sensor sensor, | ||
| - | unsigned short adc_value) | ||
| - | { | ||
| - | if (adc_value + sensor.b <= 0) | ||
| - | { | ||
| - | return -1; | ||
| - | } | ||
| - | |||
| - | return sensor.a / (adc_value + sensor.b) - sensor.k; | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | Teisenduse tegemiseks tuleb välja kutsuda // | ||
| - | < | ||
| - | <code c> | ||
| - | // Kodulabori IR kaugusmõõdiku näidisprogramm | ||
| - | // LCD ekraanil kuvatakse mõõdetud kaugus sentimeetrites | ||
| - | #include < | ||
| - | #include < | ||
| - | #include < | ||
| - | #include < | ||
| - | #include < | ||
| - | |||
| - | #define ADC_CHANNEL 0 | ||
| // Põhiprogramm | // Põhiprogramm | ||
| int main(void) | int main(void) | ||
| { | { | ||
| - | signed | + | unsigned |
| + | unsigned short reading_2; | ||
| + | unsigned short reading_3; | ||
| + | unsigned short reading_4; | ||
| char text[16]; | char text[16]; | ||
| - | |||
| - | // Robootika Kodulabor II Andurite moodul väliste andurite viik | ||
| - | //pin ex_sensors = PIN(G, 0); | ||
| - | // | ||
| - | // | ||
| // LCD ekraani seadistamine | // LCD ekraani seadistamine | ||
| lcd_gfx_init(); | lcd_gfx_init(); | ||
| lcd_gfx_clear(); | lcd_gfx_clear(); | ||
| - | lcd_gfx_goto_char_xy(1, | + | lcd_gfx_goto_char_xy(1, |
| - | lcd_gfx_write_string(" | + | lcd_gfx_write_string(" |
| - | // ADC muunduri seadistamine | + | // Väike paus |
| - | adc_init(ADC_REF_AVCC, | + | sw_delay_ms(100); |
| - | // Lõputu tsükkel | + | // Lõputu tsükkel |
| while (1) | while (1) | ||
| { | { | ||
| - | // Anduri väljundpinge 4-kordselt ümardatud väärtuse lugemine | + | // Mõõtmine |
| - | value = adc_get_average_value(ADC_CHANNEL, | + | reading_1 |
| + | // | ||
| + | reading_2 = QTR_RC_measure(pin_rc_in_2); | ||
| + | // | ||
| + | reading_3 = QTR_RC_measure(pin_rc_in_3); | ||
| + | // | ||
| + | reading_4 = QTR_RC_measure(pin_rc_in_4); | ||
| - | // ADC väärtuse kauguseks ümberarvutamine | + | // Mõõtmine õnnestus? |
| - | distance = ir_distance_calculate_cm(GP2Y0A21YK, value); | + | if (reading_1 > 0) |
| + | { | ||
| + | // Kauguse tekstiks teisendamine | ||
| + | sprintf(text, " | ||
| + | } | ||
| + | // Mõõtmisel tekkis viga? | ||
| + | else | ||
| + | { | ||
| + | // Vea tekst | ||
| + | sprintf(text, | ||
| + | } | ||
| - | lcd_gfx_goto_char_xy(1,3); | + | // Teksti kuvamine LCD teise rea alguses |
| + | lcd_gfx_goto_char_xy(3, 3); | ||
| + | lcd_gfx_write_string(text); | ||
| - | // Kauguse või veateate kuvamine | + | // Mõõtmine õnnestus? |
| - | if (distance | + | if (reading_2 |
| { | { | ||
| - | sprintf(text, | + | // Kauguse tekstiks teisendamine |
| + | sprintf(text, | ||
| } | } | ||
| + | // Mõõtmisel tekkis viga? | ||
| else | else | ||
| { | { | ||
| - | sprintf(text, | + | // Vea tekst |
| + | sprintf(text, | ||
| } | } | ||
| - | lcd_gfx_goto_char_xy(1,3); | + | // Teksti kuvamine LCD teise rea alguses |
| + | lcd_gfx_goto_char_xy(3, 4); | ||
| lcd_gfx_write_string(text); | lcd_gfx_write_string(text); | ||
| - | sw_delay_ms(500); | + | |
| + | // Mõõtmine õnnestus? | ||
| + | if (reading_3 > 0) | ||
| + | { | ||
| + | // Kauguse tekstiks teisendamine | ||
| + | sprintf(text, | ||
| + | } | ||
| + | // Mõõtmisel tekkis viga? | ||
| + | else | ||
| + | { | ||
| + | // Vea tekst | ||
| + | sprintf(text, | ||
| + | } | ||
| + | |||
| + | // Teksti kuvamine LCD teise rea alguses | ||
| + | lcd_gfx_goto_char_xy(3, | ||
| + | lcd_gfx_write_string(text); | ||
| + | |||
| + | // Mõõtmine õnnestus? | ||
| + | if (reading_4 > 0) | ||
| + | { | ||
| + | // Kauguse tekstiks teisendamine | ||
| + | sprintf(text, | ||
| + | } | ||
| + | // Mõõtmisel tekkis viga? | ||
| + | else | ||
| + | { | ||
| + | // Vea tekst | ||
| + | sprintf(text, | ||
| + | } | ||
| + | |||
| + | // Teksti kuvamine LCD teise rea alguses | ||
| + | lcd_gfx_goto_char_xy(3, | ||
| + | lcd_gfx_write_string(text); | ||
| + | |||
| + | // Väike paus | ||
| + | sw_delay_ms(100); | ||
| } | } | ||
| } | } | ||