Dallas temperatūros davikliai

Posted: 2013-09-03 in Darbeliai
Žymos:, , ,

Na, aš vis po truputį projektuoju ir eksperimentuoju su šiokiu tokiu šilumos ūkio valdymu. Galvojau, kad gal prasisuksiu su termorezistoriais, bet supratau, kad nekokia tai mintis. Jiems reikia analoginio konverterio, reikšmės nėra labai tikslios (arba reikia brangesnių ir geresnio gamintojo termorezistorių), be to, įtakos turi ir laidų ilgis su savo varža. Nors varinių laidų ji ganėtinai neženkli. Tad pasikalbėjęs su protingais draugais ir kolegomis nusprendžiau išbandyti skaitmeninius DS18B20 daviklius.

Šie davikliai yra įdomūs tuo, kad naudoja taip vadinamą vieno laido duomenų sąsają (One-wire interface). Šį išradimą padarė Dallas (dabar Maxim) kompanija. Įdomumas tame, kad ant vienos laidų poros — maitinimo-duomenų ir žemės galima prijungti daug daviklių. Kiekvienas jų turi savyje įsiūtą serijinį numeriuką, panašiai, kaip tinklo plokštės turi MAC. Todėl mikrovaldiklis gali surasti ir „apklausti“ rastus daviklius po vieną, arba iš anksto žinant serijinius numerius „bendrauti“ su reikiamais davikliais. Tai ypač patogu, jei davikliai yra fiziškai toje pačioje linijoje — galima jungti prie tų pačių laidų lygiagrečiai. Tiesa, nuskaitymo greitis dėl šios vieno laido linijos ypatumų nėra didelis, bet kiek ten tų bitukų reikia kokiai temperatūrai, drėgmei ar šiaip būsenai nuskaityti… vienas juokas.

Truputį apie pačius daviklius ir vieno laido sąsają. Davikliai turi tris kontaktus: maitinimo įtampos, duomenų linijos ir žemės. Jei laidai neilgi, iki kelių metrų, davikliai gali veikti „parazitiniu“ režimu ir naudoti duomenų liniją ir maitinimuisi, o kai linija nuskaitinėjama, vidinei energijai palaikyti jie turi mažą kondensatorių. Bet kai laidai ilgesni, rekomenduojama visgi tiesti tris laidus ir maitinimą duoti papildomai. Visgi dėl patogumo manau, kad tai labai geras variantas. Ir tie trys laidai ne tragedija. Maitinimas daviklių irgi plataus diapazono — nuo 1,8 iki 5,5 V. Tad galima juos naudoti ir su mažos energijos 3,3 V valdikliais. Arba su kokiu nors Raspberry Pi kompiuteriuku.

Ką gi, turiu kol kas vieną paskolintą davikliuką ir dar laukiu krūvelės iš draugiškosios Kinijos. Atliksiu bandymus su šiuo davikliuku.

Pirmas bandymas. Arduino valdiklis

Mane domina konkrečių daviklių „apklausa“. T.y. noriu žinoti, kokius jie turi serijinius numerius ir „apklausinėt“ pagal tai. Todėl smarkiai panaršiau ir radau tokį kodo gabaliuką, kuris vieną prijungtą daviklį apklausia ir išsiaiškina jo serijinį numerį. Jį galime išsisaugoti ir naudoti vėliau konkrečios reikšmės „apklausai“.

Tinklapis yra čia: http://arduino-info.wikispaces.com/Brick-Temperature-DS18B20

Pirmiausia sujungiau visus laidelius. Daviklio kairioji koja jungiama į žemę, vidurinė jungiama į kurį nors AVR procesoriaus elektrodą ir per 4,7 kΩ rezistorių į +5 V, o dešinioji — į +5V, jei norime duoti davikliui elektros arba į žemę, jei norime davikliui leisti dirbti parazitiniu režimu. Nepalikite dešiniosios kojos kabėti ore — daviklis gali pradėti „nusišnekėti“! Ir apskritai, jei daviklis grąžina 85 ℃, tai kažkas negerai. Man taip buvo, kai pamiršau davikliui nusiųsti temperatūros konvertavimo prašymą.

Daviklis su rezistoriumi ir laidukais atrodo šitaip:

Dallas DS18B20 daviklis prototipinėje plokštėje su 4,7 kΩ rezistoriumi | Elektronika | Darau, blė

Iš tinklapio nusikopijavau daviklių paieškos kodą bei OneWireI ir DallasTemperature bibliotekas. Susilietuvinau, kaip dažniausiai darau, programėlę ir paleidau. Konsolėje tuoj pat pasirodė užrašas su rastu vieno daviklio adresu:

Ieskau vieno laido davikliu...
Radau 'vieno laido' davikli, serijinis numeris:
0x28, 0x15, 0xF6, 0xC4, 0x04, 0x00, 0x00, 0x3D
Zia pabaiga

Štai ir viskas, šešioliktainį serijinį daviklio numerį jau turiu. Dabar galima pasidaryti greituką termometrą 🙂

Beje, nors tos bibliotekos, kurias parsisiunčiau, ir labai malonios bei patogios, bet jos visgi suryja nemažai programos atminties. Pažaidimams tai nėra blogai, bet rimtesniam darbui tai gali būti šiokia tokia kliūtis. Manau, kad gali užtekti ir OneWire bibliotekos bei kelių grynų vieno laido komandų. Jų juk reikia tik dviejų: liepti davikliui (arba visiems linijoje esantiems) išmatuoti temperatūrą ir paskui ją nuskaityti. Taip taip, tie davikliai ištisai nedirba, jie temperatūrą nustato tik paprašyti 🙂

Davikliui taip pat galima nurodyti, kokiu tikslumu jis turėtų skaičiuoti temperatūrą. Galimos reikšmės nuo 9 iki 12 bitų. Matuojant 12 bitų tikslumu daviklis užtrunka apie 750 ms (tris ketvirčius sekundės), kad nustatytų temperatūrą. Todėl tarp liepimo konvertuoti temperatūrą ir jos nuskaitymo turi būti atitinkama pauzė. Šį tikslumą reikia pasirinkti priklausomai nuo to, kaip dažnai reikia temperatūrą matuoti bei kiek svarbus tas tikslumas. Grubiai palyginus galima sakyti, kad 10 bitų tikslumu temperatūra matuojama 0,5–0,75 laipsnio tikslumu, o 12 bitų — 0,1 laipsnio tikslumu. Tik aš neteigiu, kad taip tikrai yra, tai mano atliktų bandymų apytikris pastebėjimas.

Na ką, štai ir temperatūra ekranėlyje:

 | Elektronika | Darau, blė

O palaikius daviklį tarp pirštų ir sušildžius temperatūra pakito:

Dallas DS18B20 daviklis rodo aukštesnę temperatūrą paspaudus pirštais | Elektronika | Darau, blė

Tiesa, nežinau, ar mano kambaryje tikrai 27 ℃. Šiaip atrodo, kad lyg ir ne 😀

Štai čia mano trumpos programėlės kodas su LCD ekrano paprogramėmis:

#include "Dallas_LCD.h"

#define I2C_ADDR    0x27

#define BACKLIGHT_PIN  7
#define En_pin  4
#define Rw_pin  5
#define Rs_pin  6
#define D4_pin  0
#define D5_pin  1
#define D6_pin  2
#define D7_pin  3

LiquidCrystal_I2C  lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin, BACKLIGHT_PIN, NEGATIVE);

#define ONE_WIRE_BUS_PIN 2
OneWire oneWire(ONE_WIRE_BUS_PIN);
DallasTemperature sensors(&oneWire);
DeviceAddress Probe01 = { 0x28, 0x15, 0xF6, 0xC4, 0x04, 0x00, 0x00, 0x3D };

void setup()
{
	lcd.begin (16,2);
	lcd.setBacklight(1);
	lcd.noBlink();

	sensors.begin();
	sensors.setResolution(Probe01, 12);
}

void loop()
{
	delay(1000);
        // Užprašom temperatūros konversiją iš konkretaus daviklio
	sensors.requestTemperaturesByAddress(Probe01);
        // Pauzė, kad daviklis spėtų paskaičiuoti temperatūrą
	delay(1000);
        // Nuskaitom temperatūrą
	float tempC = sensors.getTempC(Probe01);
	lcd.clear();
	if (tempC == -127.00) {
		lcd.setCursor(0, 0);
		lcd.print("Daviklio klaida!");
	} else {
		lcd.setCursor(0, 0);
		lcd.print("Temperatura:");
		lcd.setCursor(0, 1);
		lcd.print(tempC);
		lcd.print(" C");
	}
}

Visi „includai“ sudėti Dallas_LCD.h faile.

Antras bandymas. Raspberry Pi mikrokompiuteris

Su Raspberry Pi truputėlį įdomiau. Yra vienas Linux branduolio moduliukas, mokantis bendrauti vieno laido protokolu. Jis kvailai padarytas, nes šiam protokolui naudoja tik vieną GPIO elektroą, nr. 4. Pačiam nepasitaisius kodo ir nepersikompiliavus to pakeisti neįmanoma. Tai ir riboja: jei netyčia norėtųsi labai daug daviklių, tai ant vienos linijos jų kiekis yra ribotas. Būtų geriau turėti galimybę naudoti ir kitus elektrodus. Na, bet ką jau padarysi. Pradžiai užteks ir tiek, galų gale, aš savo asmeninėms reikmėms iš viso noriu tik trijų vieno laido daviklių: temperatūrai lauke, kambaryje ir drėgmei kambaryje matuoti bei šiems duomenims kaupti.

Ką gi, pradedam.

Jungimas paprastas. Maitinimą imam iš 3,3 V elektrodo. Žemę — (akivaizdu) iš žemės elektrodo. Na o duomenų liniją jungiam prie GPIO 4.

Dallas DS18B20 daviklio prijungimas prie Raspberry Pi GPIO 4 elekrodo | Elektronika | Darau, blė

Daviklis plokštėje maitinamas dabar nuo 3,3 V su tuo pačiu keliančiuoju 4,7 kΩ rezistoriumi:

Dallas DS18B20 daviklis prototipinėje plokštėje su 4,7 kΩ rezistoriumi | Elektronika | Darau, blė

Na, ir čia visas mano „serverynas“ su davikliu:

Dallas DS18B20 daviklio prijungimas prie Raspberry Pi GPIO 4 elekrodo | Elektronika | Darau, blė

Toliau štai visos komandos, kurias įvykdžiau konsolėje ir pabaigoje man parodė temperatūrą, kurią reikia dar padalinti iš tūkstančio:

pi@Uoga ~ $ sudo modprobe w1-gpio
pi@Uoga ~ $ sudo modprobe w1-therm
pi@Uoga ~ $ ls -l /sys/bus/w1/devices
total 0
lrwxrwxrwx 1 root root 0 Rgp 31 07:10 28-000004c4f615 -> ../../../devices/w1_bus_master1/28-000004c4f615
lrwxrwxrwx 1 root root 0 Rgp 31 07:10 w1_bus_master1 -> ../../../devices/w1_bus_master1
pi@Uoga ~ $ cat /sys/bus/w1/devices/28-000004c4f615/w1_slave 
a8 01 4b 46 7f ff 08 10 de : crc=de YES
a8 01 4b 46 7f ff 08 10 de t=26500
pi@Uoga ~ $

Dabar su bet kokia priimtina programėle galima nuskaitinėti failą /sys/bus/w1/devices/28-000004c4f615/w1_slave ir naudoti pagal savo poreikius. Beje, atkreipkite dėmesį, kad daviklio katalogo pavadinimas ir yra daviklio serijinis numeris. Tik baitukai išrūšiuoti priešinga tvarka, nei Arduino parodo ir naudoja.

Turėdamas laiko pasirašysiu kokią nors nedidelę programėlę temperatūros kaupimui duomenų bazėje, galėsiu lyginti visokias statistikas ir stebėti kambario bei lauko temperatūrų santykį ir pasibraižyti kokį nors grafiką. Bus įdomu.

Na, aišku, w1-gpio ir w1-therm modulius dabar galima jau įsidėti į /etc/modules failą, kad nereikėtų po kiekvieno Avietės perkrovimo šiuos modulius vėl įkėlinėti, o jie jau būtų paruošti iš anksto.

Advertisements
Komentarai
  1. Andrius parašė:

    Aš apakęs – toks įspūdis, kad 51 proc. skaitau savo mintis, tik šimtąkart kokybiškiau aprašytas 🙂 Likę procentai – dar įdomiau.
    Nemačiau, ar užsiminei kur, bet jei ne – labai gražus dalykas, tik jį reik įvaldyt, yra owfs, aš per jį esu keletą DS18B20 pajungęs. O loginimui – xively.com irgi smagu.
    Gero rašymo.

    • Darau, Blė parašė:

      Na, tai gero skaitymo toliau 🙂

      Kažkada truputį pasiskaičiau apie OWFS, tai tiesiog neradau jam panaudojimo 🙂 Per akis paprasčiausio kernelio moduliuko ar AVR kodo. Loginimui naudoju savo duombazę ir amCharts paišymui (pagal kažkieno pasiūlymą).

  2. Mindaugas parašė:

    Geras, kokybiškas straipsnis. Dėkui.
    Gal kokių pasiūlymų kaip padidinti atstumą iki daviklių, nes naudojant ilgesnį laidą pradeda pametinėti modulius? Turėjau minčių konvertuoti į RS485, bet labai jau giliai į elektroniką ir komunikacijos subtilybes pribridau.

    • Darau, Blė parašė:

      Aha, man su OneWire biblioteka ir 5 metrai kabelio buvo problematiška. Bet paskui joje susiradau kelias kodo eilutes, kurias biškį patiuninus daug kas susitvarko. Pirmas dalykas, tai visokios pauzės. Regis, mano bandyta 2007-ųjų OneWire versija buvo nustatyta ties minimaliom ribom, o su ilgesniu kabeliu jos būdavo pernelyg minimalios 🙂 Skaičiau, kad yra OneWire2, gerokai stabilesnė.

      Redaguot reikėjo OneWire::write_bit metodą, ten buvo po du delayMicroseconds kvietimus. Nepamenu reikšmių, bet tiesiog jas didinau ir padėjo.

      Iš elektrinės pusės reikėtų naudoti dvi vytas poras, iš viso keturis laidelius. Po laidelį iš kiekvienos poros jungti į „žemę“, o kitus atitinkamai į maitinimą ir duomenų kojytę. 4,7kΩ rezistorių geriau dėti linijos gale, prie paskutinio daviklio, o ne prie valdiklio. Dar galima tą rezistorių keisti į 2,2kΩ — su ilgais laidais tas padeda. Internetai pasakoja apie sėkmingus nuskaitymus per 100 metrų. Aš nežinau, taip toli nebandžiau, man užteko tik pauzikes bibliotekoj pakoreguot.

      Su RS485 būtų kaip ir patikimiau, bet atsirastų papildomas valdikliukas tame gale, ane? Na, jei pavyktų kokių ATTiny gauti papigiaja, gal ir variantas 😀

      Šiaip man Dallas davikliai gan greitai nustojo patikti. Nežinau, kaip jie kalibruoti, bet temperatūros tai pievinės nuo -5 iki +5 laipsnių nuo realios temperatūros. Aišku, galima padaryti ledo ir verdančio vandens „kalibraciją“, nu bet pisnios tai daugokai 😐 Termorezistoriai irgi ne kažką, bet bent jau pigūs ir, kiek žaidžiau, buvo tikslesni.

      Gal tamstai padės biškį Maxim pasvarstymai: https://www.maximintegrated.com/en/app-notes/index.mvp/id/148
      Ten ir apie įvairias tinklo topologijas, ir apie komutuojamus tinklus įdomiai papasakota.

  3. Mindaugas parašė:

    Geras, matau žinių tikrai sukaupęs šia kryptimi nemažai. Reiks dar sykį viską pro akis praleisti, gal kas į galvą įkris. Tas maxim Guidelines yra tikrai tai ko reikėjo ir dėkoju už gerą nuorodą. Idėja su pintomis poromis gera, turėtu sumažinti triukšmą. Realiai buvo pamąstymų apie signalo stiprinimą, tačiau labai norėjau apseiti be plokščių esdinimo / litavimo, o kažkokių kinietiškų pusfabrikačių neradau. Realiai teko bandyti switched network, kur pajungiami atskiri davikliai atšakomis, taip sumažinant bendrą tinklo talpą (kas lemia iškraipymus). Padėjo, tačiau man toks sprendimas pasirodė šiek tiek banalus ir norėjosi padaryti normalų tinklą šiems dallasams. O dėl kalibracijos ar neužtenka tiesiog padaryti šiokius tokius setpointus, kuriais patikslinti vertes? Sakykim jei prie 0 laipsniu daviklis rodo +3, visada atimti 3 nuo matavimų vertės.?

    • Darau, Blė parašė:

      Na, iš esmės gal ir užtektų atimt -3. Bet iškraipymai gali būti netiesiniai. Sakykim, ties 0 nukrypimas gali būti +3, o ties 100 kokie nors -2.

      Komutuojamas tinklas visai ne banalus 🙂 Tai netgi labai geras sprendimas. Yra ir mikroschemų, kurios tik komutavimui skirtos. Vadinasi analoginiais multiplekseriais/demultiplekseriais, pavyzdžiui, CD74HC4067.

Parašykite komentarą

Įveskite savo duomenis žemiau arba prisijunkite per socialinį tinklą:

WordPress.com Logo

Jūs komentuojate naudodamiesi savo WordPress.com paskyra. Atsijungti / Keisti )

Twitter picture

Jūs komentuojate naudodamiesi savo Twitter paskyra. Atsijungti / Keisti )

Facebook photo

Jūs komentuojate naudodamiesi savo Facebook paskyra. Atsijungti / Keisti )

Google+ photo

Jūs komentuojate naudodamiesi savo Google+ paskyra. Atsijungti / Keisti )

Connecting to %s