8 minute read

mikroupravljača (24

Shield-A, učilo za programiranje mikroupravljača (24)

ELEKTRONIKA

Advertisement

U prošlom smo nastavku upoznali temperaturni senzor DS18B20, koji s mikroupravljačem u razvojnom sustavu Shield-A komunicira preko jednobitne sabirnice, odnosno, preko samo jedne “žice”. Želimo li na istu sabirnicu povezati više komponenti 1-wire, mikroupravljač mora poznavati njihove 64-bitne serijske brojeve (adrese), jer ih samo tako može razlikovati. Kako to realizirati u praksi, pokazat ćemo sklopom prema shemi sa Slike 75. i odgovarajućim programima. 21. programski zadatak: Za sklop prema Slici 75. treba napisati program koji će komunicirati s dva temperaturna senzora DS18B20. Kada na razvojnom sustavu Shield-A pritisnemo tipkalo SW1, program treba poslati naredbu senzoru S1 da počne mjeriti temperaturu, po završetku mjerenja prihvatiti rezultat i prikazati ga na alfanumeričkom displeju. Kada pritisnemo tipkalo SW2, program treba poslati naredbu senzoru S2 da počne mjeriti temperaturu, po završetku mjerenja prihvatiti rezultat i prikazati ga na alfanumeričkom displeju. Ako tipkalo SW1 ili SW2 držimo pritisnutim duže od jedne sekunde, program treba pročitati adresu senzora S1, odnosno S2 i pospremiti je u trajnu memoriju (EEPROM). Tijekom ovog postupka, na sabirnicu smije biti povezan samo onaj senzor čija se adresa očitava! Napomena: Vrijednosti koje upišemo u EEPROM ostaju sačuvane i kada isključimo napajanje mikroupravljača; tako smo se osigurali da prilikom svakog novog uključivanja uređaja ne moramo ponovo očitavati adrese senzora! Rješenje Bascom-AVR-a (program Shield-A_21. bas) Pored varijabli koje smo koristili u prethodnom programskom primjeru trebamo još dvije u EEPROM memoriji, u koje se pohranjuju adrese temperaturnih senzora: Dim Ds18b20_adr_1(8) As Eram Byte Dim Ds18b20_adr_2(8) As Eram Byte LCD i ulazne pinove PC1 i PC2 konfiguriramo na uobičajeni način, a komunikacija 1-wire odvijat će se preko pina PC5: Config 1wire = Portc.5 Slijedi glavna programska petlja, u kojoj provjeravamo je li pritisnuto neko od tipkala i izvršavamo pridružene potprograme:

Do Debounce Pinc.1 , 0 , Sw1_sub , Sub Debounce Pinc.2 , 0 , Sw2_sub , Sub Loop

Slika 75. Na istu komunikacijsku liniju možemo povezati nekoliko komponenti 1-wire 25

Ako je pritisnuto tipkalo SW1, izvršit će se potprogram Sw1_sub, koji se razlikuje od istoimenog potprograma iz prethodnog primjera. Najprije ćemo pomoću varijable I izmjeriti koliko dugo je tipkalo pritisnuto: Sw1_sub: For I = 1 To 100 Waitms 10 If Pinc.1 = 1 Then Exit For Next Program će u petlji For-Next svakih 10 ms povećavati vrijednost varijable I i usput provjeriti je li tipkalo SW1 možda u međuvremenu otpušteno (otpušteno tipkalo odgovara stanju Pinc.1 = 1). Petlja će završiti čim se tipkalo otpusti (u tom će slučaju vrijednost varijable I biti između 1 i 100) ili kada se petlja izvrti 100 puta (to je znak da je tipkalo pritisnuto dulje od 1 s; u tom je slučaju vrijednost varijable I 101). Ako je tipkalo bilo pritisnuto kraće od 1 s, program iz EEPROM-a dohvaća adresu prvog temperaturnog senzora u niz Ds18b20_adr(), ispisuje poruku na LCD-u i izvršava potprogram Mjeri_disp_temp: If I < 100 Then For I = 1 To 8 Ds18b20_adr(i) = Ds18b20_adr_1(i) Next Home U Lcd „Temp1 = „; Gosub Mjeri_disp_temp U njemu se šalje naredba senzoru S1 da počne mjeriti temperaturu, po završetku mjerenja prihvaća rezultat i zatim prikazuje na alfanumeričkom displeju. Postupak je vrlo sličan postupku opisanom u prethodnom primjeru, osim što ovdje ne smijemo preskakati adresiranje, nego ćemo umjesto naredbe “&HCC” (skip ROM) morati adresirati senzor. Adresira se tako da na sabirnicu pošaljemo naredbu &H55, match ROM, i odmah poslije nje 64-bitnu adresu senzora S1. Čip DS18B20 koji prepozna svoju adresu ostat će aktivan i prihvatit će naredbu koju mu u nastavku šaljemo, čip koji nije adresiran “uspavat” će se i čekati novi reset. Postupak ćemo ponoviti dva puta: prije nego izdamo naredbu za početak mjerenja (naredba &H44) i prije nego zatražimo od senzora da nam pošalje rezultat mjerenja (naredba &HBE): Mjeri_disp_temp: 1wwrite &H55 ‚adresiraj DS18B20 For I = 1 To 8 1wwrite Ds18b20_adr(i) Next 1wwrite &H44 ‚pokreni mjerenje

... 1wwrite &H55 ‚adresiraj DS18B20 For I = 1 To 8 1wwrite Ds18b20_adr(i) Next 1wwrite &HBE ‚pročitaj rezultat

... Return Ako je tipkalo SW1 bilo pritisnuto duže od 1 s, ispisuje se odgovarajuća poruka na displeju i zatim poziva potprogram Citaj_disp_adr: Else Home U Lcd „DS18B20_1 adr:“ Home L Gosub Citaj_disp_adr Potprogram je identičan istoimenoj rutini iz prethodnog programa: u njemu tražimo od čipa DS18B20 da nam pošalje svoju adresu i zatim je spremamo u niz Ds18b20_adr() i ispisujemo na displeju. Adresu još trebamo zapamtiti u EEPROM-u i pričekati da se otpusti tipkalo SW1: For I = 1 To 8 Ds18b20_adr_1(i) = Ds18b20_adr(i) Next Wait 1 While Pinc.1 = 0 Wend Cls End If Return Potprogram Sw2_sub, koji pozivamo pritiskom na tipkalo SW2, identičan je, osim što umjesto senzora S1 adresira temperaturni senzor S2. Temperatura koju izmjeri S2 ispisat će se u donjem retku LCD-a, a adresa senzora S2 upisat će se u EEPROM varijablu Ds18b20_adr_2(). Rješenje Arduina (program Shield-A_21.ino) U rješenju Bascom-AVR-a vidjeli smo da je pristup EEPROM-u vrlo jednostavan, dovoljno je deklarirati varijablu kao vrstu Eram. Arduino IDE nema tu mogućnost, zato moramo napisati svoje funkcije za spremanje podataka u EEPROM i čitanje podataka iz njega. Prvo ćemo objasniti te dvije funkcije, ReadAddressFromEEPROM() i writeAddressToEEPROM().

Funkcija ReadAddressFromEEPROM() služi za čitanje niza podataka iz EEPROM-a. Njoj prosljeđujemo pokazivač na varijablu u koju ćemo zapisati pročitane podatke (u našem primjeru, adresu jednog od čipova DS18B20) i indeks pomoću kojeg izračunavamo adresu EEPROM-a na kojoj se taj podatak nalazi. U maniri programskog jezika c++, indeks prve adrese je 0. Kako se adresa čipa DS18B20 sastoji od osam bajtova, adresu EEPROM-a od koje treba početi čitati dobijemo množenjem indeksa brojem 8. Tu adresu spremamo u varijablu startEEPROM_ADDR; adresa posljednjeg bajta koji trebamo pročitati je za 7 veća i nju spremamo u varijablu stopEEPROM_ ADDR. Kada je proslijeđeni indeks 0, tada čitamo adrese EEPROM-a od 0 do 7, a kada je proslijeđeni indeks 1, tada čitamo adrese EEPROM-a od 8 do 15. Samo čitanje obavlja naredba EEPROM. read() pomoću koje, bajt po bajt, prenosimo adresu čipa DS18B20 iz EEPROM-a u niz DS_addr: void readAddressFromEEPROM(uint8_t* DS_ addr, int index){ int startEEPROM_ADDR = index * 8; int stopEEPROM_ADDR = startEEPROM_ ADDR + 7; int DS_addr_index = 0; for ( int eaddress = startEEPROM_ADDR; eaddress <= stopEEPROM_ADDR; eaddress++) { DS_addr[DS_addr_index] = EEPROM. read(eaddress); DS_addr_index++; } } // kraj readAddressFromEEPROM() Funkcija writeAddressToEEPROM() ima istu programsku logiku, osim što za spremanje podatka u EEPROM koristimo drugu naredbu, EEPROM. update(). Njoj prosljeđujemo adresu EEPROM-a i vrijednost koju želimo na nju upisati: void writeAddressToEEPROM(uint8_t* DS_addr, int index){ int startEEPROM_ADDR = index * 8; int stopEEPROM_ADDR = startEEPROM_ ADDR + 7; int DS_addr_index = 0; for ( int eaddress = startEEPROM_ADDR; eaddress <= stopEEPROM_ADDR; eaddress++) { EEPROM.update(eaddress, DS_addr[DS_ addr_index]); DS_addr_index++; } } // kraj writeAddressFromEEPROM() Napomenimo ovdje, kako EEPROM ima ograničen broj ciklusa brisanja i zapisivanja podatka. Zbog toga će naredba EEPROM.update() najprije provjeriti je li vrijednost koju želimo upisati možda jednaka vrijednosti koja je već upisana u EEPROM; stvarni upis nove vrijednosti dogodit će se samo ako se one razlikuju. Ovo ne predstavlja neku veliku korist u našem primjeru, ali produžuje vijek trajanja EEPROM-a u programima u kojima su promjene njegovog sadržaja učestale. Obje funkcije stavit ćemo na kraj našeg programa. Sada ćemo objasniti glavni program; započinjemo ga navođenjem biblioteka koje ćemo koristiti: #include <EEPROM.h> #include <LiquidCrystal.h> #include <OneWire.h> #include <DallasTemperature.h> Objekt lcd , owire i DallasTemperature definiramo na isti način kao u prethodnom primjeru, a zatim još definiramo i nizove u koje ćemo spremiti adrese obaju čipova DS18B20: uint8_t Ds18b20_adr_1[8], Ds18b20_adr_2[8]; Funkcija setup() vrlo je slična kao u prethodnom zadatku. Dodali smo joj našu funkciju za čitanje adresa iz EEPROM-a, koje spremamo u prije spomenute nizove Ds18b20_adr_1 i Ds18b20_adr_2. void setup() { pinMode(17, OUTPUT); digitalWrite(17, HIGH); pinMode(A1, INPUT_PULLUP); pinMode(A2, INPUT_PULLUP);

lcd.begin(16, 2); lcd.print(„ABC Shield-A P21“);

senzori.begin(); readAddressFromEEPROM(Ds18b20_adr_1,

0);

readAddressFromEEPROM(Ds18b20_adr_2, 1); } // kraj setup() Funkcija loop() identična je onoj iz prethodnog zadatka. U funkciji sw1_function() provjeravamo koliko je dugo pritisnuta tipka SW1 na isti način na koji je to napravljeno u rješenju Bascom-AVR-a: void sw1_function(){ int i;

for (i = 0; i <= 100; i++){ delay(10); if (digitalRead(A1) == 1) break; } Ukoliko je tipka pritisnuta kraće od jedne sekunde, ispisujemo očitanu vrijednost prvog senzora na LCD. U prethodnom zadatku koristili smo funkciju koja svim senzorima šalje zahtjev za mjerenje temperature i očitavali smo temperaturu senzora s indeksom 0. Ovaj put koristit ćemo funkcije senzori.requestTemperaturesByAddress() i senzori.getTempC() kojima prosljeđujemo adresu senzora s kojeg želimo očitati temperaturu: if ( i < 100 ) { lcd.setCursor(0,0); lcd.print(„Temp1 = „); lcd.setCursor(8,0); senzori.requestTemperaturesByAddress(Ds 18b20_adr_1); float tempC = senzori.getTempC(Ds18b20_ adr_1); if(tempC == DEVICE_DISCONNECTED_C) { lcd.print(„DS18B20?“); return; } lcd.print(tempC); Ukoliko je tipka pritisnuta dulje od jedne sekunde, koristimo isti algoritam kao u funkciji sw2_function() iz prethodnog zadatka. Razlika je samo u tome što sada koristimo niz Ds18b20_ adr_1 za spremanje adrese čipa DS18B20 i funkciju writeAddressToEEPROM() za njen upis u EEPROM: } else { lcd.clear(); lcd.setCursor(0,0); lcd.print(„DS18B20_1 adr: „); lcd.setCursor(0,1); if (senzori.getAddress(Ds18b20_adr_1, 0)) { for (uint8_t i = 0; i < 8; i++) { if (Ds18b20_adr_1[i] < 16) lcd.print(„0“); lcd.print(Ds18b20_adr_1[i], HEX); } writeAddressToEEPROM(Ds18b20_adr_1,

0);

} else { lcd.print(„DS18B20?“); } delay(1000); lcd.clear();

} } // kraj sw1_function() Funkcija sw2_function() algoritamski je identična funkciji sw1_function(); razlika je samo u tome, što u njoj koristimo niz Ds18b20_adr_2, a funkciji writeAddressToEEPROM() prosljeđujemo indeks 1 prilikom upisa adrese u EEPROM. void sw2_function(){

... senzori.requestTemperaturesByAddress(Ds 18b20_adr_2);

... writeAddressToEEPROM(Ds18b20_adr_2, 1);

... } // kraj sw2_function()

Kako koristiti program Shield-A_21 Prije prvog mjerenja temperature inicijalizirat ćemo sustav: • spojimo samo senzor S1 i dužim pritiskom na tipkalo SW1 očitamo njegovu adresu • spojimo samo senzor S2 i dužim pritiskom na tipkalo SW2 očitamo njegovu adresu. Mikroupravljač u razvojnom sustavu Shield-A sada poznaje adrese spojenih senzora DS18B20 pa kratkim pritiscima na tipkala SW1 i SW2

Slika 76. Poruke programa Shield-A_21 na LCD-u

This article is from: