======= 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);
}