======= Arduino vihiku harjutuste lahendused ====== === Harjutus #1.1 === /* Nimetus: Näide #1.1 Digitaalsed sisend-väljundid Kirjeldus: Nuppu korraks vajutades vilgub LED 3 korda */ // Konstandid const int nupp = A0; // Viik kuhu on ühendatud nupp const int led = 13; // Viik kuhu on ühendatud roheline LED // Globaalsed muutujad int nupuOlek = 0; // Nupu oleku muutuja ja algväärtustamine void setup() { pinMode(led, OUTPUT); // algväärtustame LED viigu väljundiks pinMode(nupp, INPUT_PULLUP); // algväärtustame nupu viigu sisendiks ja aktiveerime sisemise pull-up takisti } void loop(){ nupuOlek = digitalRead(nupp); // salvestame muutujasse nupu hetke väärtuse if (nupuOlek == LOW) { // Kui nupu on alla vajutatud for(int i = 0; i < 3; i++){ digitalWrite(led, HIGH); // süütame LED-i delay(200); //viide led põlemas hoidmiseks digitalWrite(led, LOW); // kustutame LED-i delay(200); //viide led kustus hoidmiseks } } } === Harjutus #1.2 === NB! LED vilkumisel on sees pikad viited, mistõttu vilkumise välja lülitamiseks tuleb lülitit pikemalt all hoida. /* Nimetus: Näide #1.2 Digitaalsed sisend-väljundid Kirjeldus: LED vilkumise sisse/välja lülitamine lülitiga */ // Konstandid const int nupp = A0; // Viik kuhu on ühendatud nupp const int led = 13; // Viik kuhu on ühendatud roheline LED // Globaalsed muutujad bool vilguta = false; //muutuja vilgutamise sisse välja lülitamiseks void setup() { pinMode(led, OUTPUT); // algväärtustame LED viigu väljundiks pinMode(nupp, INPUT_PULLUP); // algväärtustame nupu viigu sisendiks ja aktiveerime sisemise pull-up takisti } // Algus identne näitega #1.1 void loop(){ if(digitalRead(nupp) == LOW){ //kontrolli kas lülitit on vajutatud vilguta = !vilguta; //inverteerime vilgutamise muutuja, et vilkumine sisse/välja lülitada delay(50); //kontaktide värelemise viide (debounce) while(digitalRead(nupp) == LOW); //ootab kuni nupp lastakse lahti } if (vilguta == 1) { // Kui nupu olek on madal delay(1000); //led kustus hoidmise viide digitalWrite(led, HIGH); // süütame LED-i delay(1000); // led põlemas hoidmise viide } digitalWrite(led, LOW); // kustutame LED-i } === Harjutus #1.3 === /* Nimetus: Näide #1.3 Digitaalsed sisend-väljundid Kirjeldus: Iga nupu vajutusega vilgub LED aina rohkem kordi */ // Konstandid const int nupp = A0; // Viik kuhu on ühendatud nupp const int led = 13; // Viik kuhu on ühendatud roheline LED // Globaalsed muutujad int nupuVajutusi = 0; void setup() { pinMode(led, OUTPUT); // algväärtustame LED viigu väljundiks pinMode(nupp, INPUT_PULLUP); // algväärtustame nupu viigu sisendiks ja aktiveerime sisemise pull-up takisti } void loop() { if (digitalRead(nupp) == LOW) { // kontrollib kas nupu olek on madal nupuVajutusi++; //liidame ühe muutuja väärtusele delay(50); //lüliti kontaktide värelemise (debounce) efekti mõju vähendamiseks väike viide while (digitalRead(nupp) == LOW) { //tsükkel jätkub lõputult kuni nupu olek on madal // Ootame nupu lahtilaskmist } for(int i = 0; i < nupuVajutusi*2;i++){ digitalWrite(led, !digitalRead(led)); // LED viigu väljund inverteeritakse kasutades viigu hetke olekut delay(200); //viide, et hoida led kustus/põlemas } delay(50); //lüliti kontaktide värelemise (debounce) efekti mõju vähendamiseks väike viide } } === Harjutus 2.1 === /* Nimetus: Näide #2.1 LED juhtimine potentsiomeetriga Kirjeldus: Potentsiomeetri pööramisel üle etteantud piiri süttib LED */ const int pote = A0; // määrame potentsiomeetri ühendusviigu (sisend) const int led = 13; // määrame LED ühendusviigu (väljund) int poteOlek = 0; // muutuja potentsiomeetri väärtuse salvestamiseks void setup() { //mikrokontrolleri viigud on tavaolekus sisendid pinMode(led, OUTPUT); // algväärtustame LED viigu väljundiks } void loop() { poteOlek = analogRead(pote); // loeme anduri väärtuse if(poteOlek >= 1023 || poteOlek <= 0)digitalWrite(led, HIGH); // kustutame LED-i else digitalWrite(led, LOW); // süütame LED-i } === Harjutus 2.2 === /* Nimetus: Näide #2.2 LED juhtimine potentsiomeetriga Kirjeldus: Potentsiomeetri asendist sõltub LED vilkumise sagedus */ const int pote = A0; // määrame potentsiomeetri ühendusviigu (sisend) const int led = 13; // määrame LED ühendusviigu (väljund) const int fikseeritud_viide = 512; int poteOlek = 0; // muutuja potentsiomeetri väärtuse salvestamiseks void setup() { //mikrokontrolleri viigud on tavaolekus sisendid pinMode(led, OUTPUT); // algväärtustame LED viigu väljundiks } void loop() { poteOlek = analogRead(pote); // loeme anduri väärtuse digitalWrite(led, HIGH); // kustutame LED-i if(poteOlek > 512) delay(1023 - poteOlek); // tekitame viite millisekundit else delay(fikseeritud_viide); // tekitame viite millisekundit digitalWrite(led, LOW); // süütame LED-i if(poteOlek < 512) delay(poteOlek); // tekitame viite millisekundit else delay(fikseeritud_viide); // tekitame viite millisekundit } === Harjutus 2.3 === /* Nimetus: Näide #2.3 LED juhtimine potentsiomeetriga Kirjeldus: Potentsiomeetri asendi muutuse kiiruse järgi LED heleduse reguleerimine */ //Konstandid const int pote = A0; // määrame potentsiomeetri ühendusviigu (sisend) const int led = 13; // määrame LED ühendusviigu (väljund) const int maxLoendurVaartus = 150; //Globaalsed muutujad int poteOlek = 0; int viimanePoteOlek = 0; int kiirus = 0; int loendur = 0; void setup() { //mikrokontrolleri viigud on tavaolekus sisendid pinMode(led, OUTPUT); // algväärtustame LED viigu väljundiks } void loop() { poteOlek = analogRead(pote); // loeme anduri hetkeväärtuse //Arvutame kiiruse anduri hetkeväärtuse ja eelneva väärtuse lahutustehtena //Olenevalt kumb pidi potentsiomeetri liigutab on vaja ka tehe teha ühte //või teistpidi, et ei tekiks negatiivset arvu if(poteOlek > viimanePoteOlek) kiirus = poteOlek - viimanePoteOlek; else kiirus = viimanePoteOlek - poteOlek; if(kiirus > 100) kiirus = 100; //piirab kiiruse väärtuse ära, et ei tekiks negatiivset viidet //kui potentsiomeetr ei liigu, siis võib siiski analoog-digitaal muunduri müra tõttu led tuhmilt põleda. //Selle olukorra eemaldamiseks seame minimaalse kiiruse väärtuse, millest alates LED põlema võib minna if(kiirus > 5){ digitalWrite(led, HIGH); // süütab LED-i delayMicroseconds(kiirus); // hoia LED põlemas kiiruse väärtusega võrdne arv mikrosekundeid } digitalWrite(led, LOW); //kustutab LED-i delayMicroseconds(100 - kiirus); // hoia LED kustus 100st mikrosekundist ülejäänud arv mikrosekundeid //Kuna PWM signaali ehk LED heleduse reguleerimiseks peab loop() tsükkel võimalikult kiirelt töötama, //siis ei saa lisanduvaid viiteid lubada, et led põleks võimalikult stabiilselt. Samas potentsiomeetri //hetke väärtuse ja eelneva väärtuse uuendamise vahe on liiga väike, et tekiks adekvaatne kiiruse väärtus. //Probleemi lahenduseks on kasutatud viite tekitamiseks muutuja suurendamise meetodit, mis jõudes ette //antud väärtuseni teeb tegevuse ja nullib loenduri. loendur++; //suurenda muutujat loendur ühe võrra if(loendur >= maxLoendurVaartus){ viimanePoteOlek = poteOlek; //uuenda eelmise potentsiomeetri väärtust loendur = 0; // nulli loendur } } === Harjutus 3.1 === /* Nimetus: Näide #3.1 16x2 tähemärgilise LCD kasutamine Kirjeldus:Kasutab LiquidCrystal.h teeki ja 2x16 täheärgilist LCD laiendusplaati */ #include // Kaasame vajaliku teegi // Initsialiseerime LCD koos vastavate viikude ühendamisega LiquidCrystal lcd(8, 9, 4, 5, 6, 7); void setup() { lcd.begin(16, 2); //Määrame LCD read ja veerud lcd.print(" Tere Tallinn! "); // Trükime tervitusteksti } void loop() { lcd.setCursor(7, 1); //Viime kursori teisele reale seitsmendale veerule (2. rida on indeksiga 1) lcd.print(millis()/1000); //Trükime loenduri väärtuse } === Harjutus 3.2 === #include // initialize the library LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //Erikujuliste tähemärkide 2-dimensiooniline massiiv byte symbolid[8][8] = { {0b00100,0b00100,0b00000,0b00000,0b00000,0b00100,0b01110,0b10101}, {0b00100,0b00000,0b00000,0b00000,0b00100,0b01110,0b10101,0b00100}, {0b00000,0b00000,0b00000,0b00100,0b01110,0b10101,0b00100,0b00100}, {0b00000,0b00000,0b00100,0b01110,0b10101,0b00100,0b00100,0b00000}, {0b00000,0b00100,0b01110,0b10101,0b00100,0b00100,0b00000,0b00000}, {0b00100,0b01110,0b10101,0b00100,0b00100,0b00000,0b00000,0b00000}, {0b01110,0b10101,0b00100,0b00100,0b00000,0b00000,0b00000,0b00100}, {0b10101,0b00100,0b00100,0b00000,0b00000,0b00000,0b00100,0b01110}}; void setup() { for(int i = 0; i < 8; i++) lcd.createChar(i,symbolid[i]); // tekitab eriskujulised tähemärgid lcd.begin(16, 2); // seadistab ekraani suuruse } void loop() { //tsükkel kuva järjest kõik 8 tekitautd erikujulist tähemärki for(int i = 0; i < 8; i++){ lcd.setCursor(0,0); // seadistab kursori positsioon veerule 0 ja reale 0 for(int k = 0; k < 16; k++) lcd.write((uint8_t)i); //kuvab erikujulise tähemärgid kogu esimesele reale lcd.setCursor(0,1); // seadista kursori positsioon veerule 0 ja reale 1 for(int k = 0; k < 16; k++) lcd.write((uint8_t)i); // kuvab erikujulise tähemärgi kogu teisele reale delay(100); //viide et tähemärgid LCD-l ei uueneks liiga kiirelt } } === Harjutus 3.3 === /* Nimetus: Harjutus #3.3 16x2 tähemärgilise LCD kasutamine Kirjeldus: Kasutab LiquidCrystal.h teeki ja ITEAD Studio 2x16 LCD teksti laiendusplaati */ #include // Kaasame vajaliku teegi LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //tekitame objekti ja seome vastavad ühendusviigud sellega //defineerime lihtsustamiseks konstandi igale nupule #define nuppRIGHT 0 #define nuppUP 1 #define nuppDOWN 2 #define nuppLEFT 3 #define nuppSELECT 4 #define nuppNONE 5 int vajutatudNupp, nupuSisend, positsioon = 0; int rida = 0, veerg = 0; void setup() { lcd.begin(16, 2); //Määrame LCD read ja veerud lcd.print("ADC: "); //Trükime analoogsisendi väärtuse lcd.print(analogRead(A0)); } void loop() { vajutatudNupp = kontrolliNuppe(); //võtab analoog mõõtmise ja võrdleb ette antud väärtustega //kontrollib kas mõni nupp on alla vajutatud if(vajutatudNupp < 5){ lcd.clear(); //puhastab ekraani ja liigutab kursori tagasi algasendisse //vastavalt vajutatud nupule muuda kursori asukohta enne teksti trükkimist ekraanile if(vajutatudNupp == 0) veerg =8; if(vajutatudNupp == 1) rida = 0; if(vajutatudNupp == 2) rida = 1; if(vajutatudNupp == 3) veerg = 0; lcd.setCursor(veerg, rida); //sead kursori positsiooni LCD-l lcd.print("ADC: "); //teksti kuvamine ekraanil lcd.print(nupuSisend); //muutuja väärtuse kuvamine ekraanil delay(200); //lühike viide, et ekraanil väärtust liiga kiirelt ei uuendataks } } //Funktsioon võtab analoog sisendi väärtuse ja võrdleb olemasolevate väärtustega. //Tagastab arvu vahemikus 0 kuni 5 vastavalt defineeritud konstandile int kontrolliNuppe() { nupuSisend = analogRead(A0); //võtab analoog väärtuse viigult A0. if (nupuSisend < 50) return nuppRIGHT; //parem nupp if (nupuSisend < 195) return nuppUP; //ülemine nupp if (nupuSisend < 380) return nuppDOWN; //alumine nupp if (nupuSisend < 555) return nuppLEFT; //vasak nupp if (nupuSisend < 790) return nuppSELECT; //valiku nupp return nuppNONE; // kui ühtegi nuppu pole vajutatud, siis tagastatakse nuppNONE } === Harjutus 4.1 === /* Nimetus: Näide #3 ... Kirjeldus: */ // Kaasame vajalikud teegid #include #include LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // Initsialiseerime LCD koos vastavate viikude ühendamisega const int pote_sisend = A1; // määrame potentsiomeetri sisendviigu const int NTC_sisend = A2; // määrame temperatuurianduri sisendviigu const int led = 10; // määrame LED ühendusviigu const int nupp = A0; // määrame nupu ühendusviigu // Globaalsed muutujad int pote = 0; long ntc = 0; double temperatuur = 0; int seade = -1; void setup() { pinMode(led, OUTPUT); //Seadistame LED viigu väljundiks pinMode(nupp, INPUT); //Algväärtustame nupu viigu sisendiks lcd.begin(16, 2); //Määrame LCD read ja veerud //Kuvame ekraanile esialgse seade väärtuse lcd.setCursor(0, 1); lcd.print("Seade: "); lcd.setCursor(7, 1); lcd.print(seade); } void loop() { //Loeme potensiomeetri väärtuse ja teisendame vahemikku -20 kuni 100 pote = map(analogRead(pote_sisend),0,1023,-20,100); ntc = analogRead(NTC_sisend); //Loeme temperatuuri anduri väärtuse //Teisendame temperatuurianduri väärtuse temperatuuriks temperatuur = log(((10240000/ntc) - 10000)); temperatuur = 1/(0.001129148 + (0.000234125 + (0.0000000876741 * temperatuur * temperatuur))* temperatuur); temperatuur = temperatuur - 273.15; //Konverteeri Kelvinid Celciustesse //Kuvame informatsiooni LCD ekraanile lcd.setCursor(0, 0); lcd.print("Pot: "); lcd.setCursor(4, 0); lcd.print(pote); lcd.setCursor(8, 0); lcd.print("Tmp: "); lcd.setCursor(12, 0); lcd.print(temperatuur); //Kui nupule vajutatakse, salvesta seadesuurus if(digitalRead(nupp) == LOW) { seade = pote; lcd.setCursor(0, 1); lcd.print("Seade: "); lcd.setCursor(7, 1); lcd.print(seade); } // Kui temperatuur on kõrgem potensiomeetriga seatud väärtusest ja nuppu pole alla vajutatud if((temperatuur > seade) && (digitalRead(nupp) == HIGH)) { digitalWrite(led, HIGH); //Süütame LED-i } else { digitalWrite(led, LOW); //Vastasel korral kustutame LED-i } } === Harjutus 4.2 === /* Nimetus: Näide #3.2 Kaugusandurite lugemine Kirjeldus: Kaugusandurite lugemine */ #include //Kaasame vajaliku teegi // Initsialiseerime LCD koos vastavate viikude ühendamisega LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //Määrame andurite ühendusviigud const int analoogAndur = A2; const int digiAndur = A3; int analoogAndurVaartus, digitaalAndurVaartus; void setup() { lcd.begin(16, 2); //Määrame LCD read ja veerud //kirjutame ekraanile selgitavad tekstid lcd.print("Analoog:"); lcd.setCursor(0, 1); lcd.print("Digi:"); } void loop() { analoogAndurVaartus = analogRead(analoogAndur); //Loeme analoog kaugusanduri väärtuse // https://acroname.com/articles/linearizing-sharp-ranger-data analoogAndurVaartus = (6787/(analoogAndurVaartus-3)-4); //valemi järgi lineariseerimine ja konverteerimine sentimeetriteks digitaalAndurVaartus = digitalRead(digiAndur); //Loeme digitaalse lähedusanduri väärtuse lcd.setCursor(9, 0); //Nihutame kursori esimesele reale positsioonile 9 lcd.print(analoogAndurVaartus); //Trükime ekraanile analoog anduri väärtuse lcd.print(" "); //Kirjutame üle järgnevad kolm ruutu tühikutega, et vana lugemi väärtus ei jääks näha lcd.setCursor(9, 1); //Nihutame kursori teisele reale positsioonile 9 lcd.print(digitaalAndurVaartus); //Trükime ekraanile digitaal anduri väärtuse delay(200); // Lühike viide, et tekst ekraanil oleks loetav } === Harjutus 5.1 === === Harjutus 5.2 === === Harjutus 5.3 === /* Description */ #include "U8glib.h" // setup u8g object, please remove comment from one of the following constructor calls // IMPORTANT NOTE: The complete list of supported devices is here: http://code.google.com/p/u8glib/wiki/device U8GLIB_NHD_C12864 u8g(13, 11, 10, 9, 8); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8 #define KEY_NONE 0 #define KEY_PREV 1 #define KEY_NEXT 2 #define KEY_SELECT 3 #define KEY_BACK 4 uint8_t uiKeyCodeFirst = KEY_NONE; uint8_t uiKeyCodeSecond = KEY_NONE; uint8_t uiKeyCode = KEY_NONE; int adc_key_in; int key=-1; int oldkey=-1; int selectedType = 0; // Convert ADC value to key number // 4 // | // 0 -- 1 -- 3 // | // 2 int get_key(unsigned int input) { if (input < 100) return 0; else if (input < 300) return 1; else if (input < 500) return 2; else if (input < 700) return 3; else if (input < 900) return 4; else return -1; } void uiStep(void) { adc_key_in = analogRead(0); // read the value from the sensor key = get_key(adc_key_in); // convert into key press if (key != oldkey) // if keypress is detected { delay(50); // wait for debounce time adc_key_in = analogRead(0); // read the value from the sensor key = get_key(adc_key_in); // convert into key press if (key != oldkey) { oldkey = key; if (key >=0){ //Serial.println(key); if ( key == 0 ) uiKeyCodeFirst = KEY_BACK; else if ( key == 1 ) uiKeyCodeFirst = KEY_SELECT; else if ( key == 2 ) uiKeyCodeFirst = KEY_NEXT; else if ( key == 4 ) uiKeyCodeFirst = KEY_PREV; else uiKeyCodeFirst = KEY_NONE; uiKeyCode = uiKeyCodeFirst; } } } delay(100); } #define MENU_ITEMS 6 char *menu_strings[MENU_ITEMS] = { "ITT Group OU", "www.ittgroup.ee", "Akadeemia tee 21", "B-127" ,"Tallinn 12618","Tel. 6566614"}; uint8_t menu_current = 0; uint8_t menu_redraw_required = 0; uint8_t last_key_code = KEY_NONE; void drawMenu(void) { uint8_t i, h; u8g_uint_t w, d; u8g.setFont(u8g_font_6x12);//4x6 5x7 5x8 6x10 6x12 6x13 u8g.setFontRefHeightText(); u8g.setFontPosTop(); h = u8g.getFontAscent()-u8g.getFontDescent(); w = u8g.getWidth(); for( i = 0; i < MENU_ITEMS; i++ ) { d = (w-u8g.getStrWidth(menu_strings[i]))/2; u8g.setDefaultForegroundColor(); if ( i == menu_current ) { if(selectedType) u8g.drawRFrame(0, i*h+1, w, h,1); else{ u8g.drawBox(0, i*h+1, w, h); u8g.setDefaultBackgroundColor(); } //u8g.setDefaultBackgroundColor(); } u8g.drawStr(d, i*h+1, menu_strings[i]); } } void updateMenu(void) { switch ( uiKeyCode ) { case KEY_NEXT: menu_current++; if ( menu_current >= MENU_ITEMS )menu_current = 0; menu_redraw_required = 1; break; case KEY_PREV: if ( menu_current == 0 )menu_current = MENU_ITEMS; menu_current--; menu_redraw_required = 1; break; case KEY_SELECT: selectedType = !selectedType; menu_redraw_required = 1; break; } uiKeyCode = KEY_NONE; } void setup() { u8g.setRot180();// rotate screen, if required u8g.setContrast(0); // seadsita ekraani kontrastsus (LCD plaadist sõltuv) menu_redraw_required = 1; // force initial redraw //Serial.begin(9600); } void loop() { uiStep(); // check for key press updateMenu(); // update menu bar if ( menu_redraw_required != 0 ) { u8g.firstPage(); do { drawMenu(); } while( u8g.nextPage() ); menu_redraw_required = 0; } } === Harjutus 6.1 === === Harjutus 7.1 === /* Nimetus: Näide #7.1 Servomootor Kirjeldus: Servomootori juhtimine PWM signaaliga */ // Kaasame vajalikud teegid #include Servo mootor; // tekitame teegist ühe servo objekti const int pote = A1; // määrame potentsiomeetri sisendviigu const int lahedusAndur = A4; int mootoriSuund = 1; //mootori liikumise suunda määrav muutuja (algväärtustatud paremale pöörama) int servoAsend = 90; //servo hetkepositsiooni hoidev muutuja (algväärtustatud keskpositsiooni) int naebObjekti; //lahedusAnduri väärtust hoidev muutuja void setup() { mootor.attach(A5); //servo objekti sidumine kindla viiguga mootor.write(servoAsend); while(digitalRead(lahedusAndur) == 1); } void loop() { naebObjekti = digitalRead(lahedusAndur); if(naebObjekti == 1){ if(mootoriSuund == 1){ servoAsend += 10; } else{ servoAsend -= 10; } delay(50); //viide, et servo jõuaks uude positsiooni jõuda } else{ //kui andur näeb midagi, siis mootori asend ei muutu } if(servoAsend >=180){ servoAsend = 180; mootoriSuund = -1; } if(servoAsend <= 0){ servoAsend = 0; mootoriSuund = 1; } mootor.write(servoAsend); }