Termometrai DS18B20 ir USART

Posted: 2018-01-04 in Darbeliai
Žymos:, ,

Iki šiol skaitmeninius termometrus DS18B20 naudojau tik su Atmel procesoriais ir pagalbine Arduino programine periferija. Pagrindas yra OneWire biblioteka bei ant jos užtempta Dallas Temperature Control biblioteka. OneWire biblioteka paremta bitbanginimu, t.y. pilnai programiniu mikrovaldiklio kojytės „baksnojimu“. Tai reiškia, kad procesoriukas gan smarkiai apkraunamas, nes reikia programiškai išlaikyti tinkamas pauzes ir tuo metu nieko neveikti. Dar ir neleisti pertraukimų.

Aš pagalvojau, kad prie savo šviesos projekto galėčiau pridėti ir temperatūrų nuskaitymą. Na, neskaitant keleto termistorių, kurie stebės įrangos temperatūrą ir signalizuos pavojus. Būtų gerai tiesiog papildomai turėt galimybę nuskaityt temperatūrą ir didesniam kiekiui daviklių: būtų galima stebėti relių ir 12 V maitinimo šaltinių būsenas. Pasignalizuot, jei kuris aparatas sugalvotų užsidegt 😀

Pirmasis dalykas: sunkiai radau šių termometrų, tiksliau, OneWire bibliotekų ARM procesoriams. Kažkaip keistai pasijutau, nu negi niekam nereikėjo? Na, reikėjo. Bet tos bibliotekos vėlgi tokios ganėtinai apkrautos, visokie papildomi laikmačiai paleidžiami pauzių išlaikymasm. Brrr.

Aš suprantu, kad su Arduino/Atmel bitbanginimas yra pats įprasčiausias metodas, nes pigieji procesoriukai turi vos po vieną USARTą. Jis paliekamas komunikacijai su kompiuteriu ir firmwarės įrašinėjimui. Tuo tarpu mano pigienos STM32F103C8T6 turi tris USART’us. Ir dar po du kojų rinkinius — pirminį ir alternatyvųjį. Tai jeigu aš USART1 palieku debuginimui ir firmwarės įrašymui, dar lieka USART2 ir USART3. Mano suprojektuotas mygtukų valdiklis turi papildomų įvesčių krūvelę, kurias dar nesugalvojau, kam naudoti. Ir viena iš jų yra USART2.

Ko aš čia dabar apie tuos USART? Ogi USART’as iš principo yra labai patogus aparatūrinis įrenginys, galintis apsimesti OneWire masteriu. Oficialiai, pagal Maxim Integrated. Per daug nesigilinant gaunasi, kad per USARTą išsiųstas/nuskaitytas baitas atitinka vieną OneWire bitą, jei nustatytas greitis yra 115200 bodų. Tuo tarpu baitas 0xF0 išsiųstas 9600 bodų greičiu puikiai atitinka reset pulse’ą.

Trumpai, kaip veikia OneWire magistralė. Kad pradėtų komunikaciją, masteris turi išsiųsti reset pulse, t.y. duomenų liniją laikyti ant loginio nulio (užtrumpintą į „žemę“) apie 480 µs. Keturi nuliukai baite 9600 bodų greičiu maždaug tiek ir yra. Po šito impulso OneWire įrenginukai pasiruošia duomenų priėmimui/perdavimui, t.y. komunikacijai. Kas tada vyksta toliau? Prieš išsiųsdamas vienetuką masteris turi 10 µs palaikyti loginį nulį, o paskui 50-60 µs — loginį vienetą. Išsiųsdamas nulį — tiesiog palaikyti loginį nulį apie 60-70 µs. Šį reikalą darant su USART užtenka išsiųsti pilnai užpildytą baitą 0xFF arba nuliuką 0x00 115200 bodų greičiu. Sakysite, o kaip tas 10 µs impulsas siunčiant vienetą? Ogi paprastai, juk USART’as visada prieš siųsdamas baitą išsiunčia vieną nulinį bitą 🙂 115200 greičiu šitas start-bitas ir yra 10 µs. Nuskaitant tas pats. Masteris turi 10 µs palaikyti liniją ant loginio vieneto, o paskui kitas 50-60 µs stebėti, kas bus — jei elektrinis signalas kris į „žemę“ — tai bus nuliukas, o jei ne — bus vienetukas.

Toliau daromas toks „hakas“. Mikrovaldiklio TX ir RX kojelės sujungiamos į krūvą (arba per diodą, paaiškinsiu vėliau) ir prijungiamos prie OneWire duomenų linijos. Kas išsiunčiama per RX, gaunama į TX, „echo“ režimas 🙂 Bet čia naudojamas toks fintas. Kai norima nuskaityti baitą, siunčiamas 0xFF į TX, tipo, padarom trumpą impulsą su start-bitu. Tada per RX nuskaitinėjam. Jei OneWire daviklis siųs vienetuką, jis linijos nejudins ir į RX taip pat grįš 0xFF. O va jeigu jis norės siųsti nuliuką ir bent kažkuriam laikui užtrumpins liniją į „žemę“, tai išsiuntus 0xFF atgal grįš kažkokia kita reikšmė. Taip ir žinom, ar nuliukas parėjo, ar vienetukas.

Tikiuosi, kad dar nesusipainiojot 🙂

Na, bet dabar aš minėjau tokį dalyką, kaip diodas. Kam? Įsivaizduokim jungimo schemą, kai kojytės tiesiog krūvoj:

Daviklis ds18b20 prijungtas prie stm32f103 | Elektronika | Darau, blė

Problema yra tokia: jei TX kojytė vienetuką signalizuoja prijungdama 3,3 V (loginį vienetą), tai temperatūros daviklis siųsdamas duomenis ir perduodamas loginį nulį prijungs savo DQ kojytę prie žemės — o taip TX kojytės loginis vienetas bus tiesiogine to žodžio prasme užtrumpintas ir lengvai gali sudegti. Dėl šios priežasties ARM mikrovaldiklyje TX reikia sukonfigūruoti, kaip „Open drain“: t.y. kai perduodamas vienetas, ta kojytė lieka „kaboti ore“, o kai nulis — ji trumpinama į žemę. Kadangi vienetą palaiko 4,7k rezistorius (tokia jo ir prasmė), tai RX sujungtas su TX jokios žalos nepadaro.

Jei kokio Arduino procesoriuko USARTą norėtumėt panaudoti šitam reikalui, tai ten reikėtų apsauginio diodo, nes AVR procesorių kojytės „Output“ režime neturi „Open drain“ varianto:

Daviklis ds18b20 prijungtas prie stm32f103 per Šotkio diodą | Elektronika | Darau, blė

Tai va kaip ir tiek. Pasirašiau kol kas nebaigtą USART-OneWire bibliotekėlę. Nusprendžiau ją įgyvendinti trimis variantais: paprasto bitbangingo, USART ir USART+DMA. Pastarasis variantas ypač vilioja, nes galima procesoriuko ciklų sutaupyt, ypač su kokiu FreeRTOS multitaskingą gaminant. Bet kol kas nepavyksta. Dabartinė bibliotekėlės stadija yra paprastas USART išnaudojimas. Ruošiuosi ir konkrečiai paties DS18B20 daviklio apdorojimo bibliotekėlę sulipdyt, bet čia ateity. Tuo tarpu galite dabartinę mano bibliotekėlę pasiimti ir naudoti, užkūriau savo (ir jūsų) reikmėms GitHubo paskyrą: https://github.com/darauble/STM32-ARM-Libs

Tą biblioteką kartu su DS18B20 nuskaitymo užuomazgomis naudojanti programulkė:

#include <stdio.h>
#include "stm32f10x.h"
#include "onewire_usart_dma.h"
#include "usart_utils.h"
#include "makrosai.h"
#include "dallas.h"

char buf[100];
uint8_t scratch_pad[__SCR_LENGTH];
uint8_t dev_count;
uint8_t dev_addr[10][8];

int main(void)
{
    REMAP_JTAG_FULL_DISABLE;
    uint32_t i;
    owu_struct_t o2;

    owu_init(USART3, &o2);

    enable_usart(USART1, 115200);
    print_usart(USART1, "Pradedam OWU\r\n");

    uint8_t presence;

    dev_count = 0;
    while(owu_search(&o2, dev_addr[dev_count])) {
        snprintf(buf, 99, "Device found %d: 0x%02X%02X%02X%02X%02X%02X%02X%02X\r\n", dev_count,
        dev_addr[dev_count][0], dev_addr[dev_count][1], dev_addr[dev_count][2], dev_addr[dev_count][3],
        dev_addr[dev_count][4], dev_addr[dev_count][5], dev_addr[dev_count][6], dev_addr[dev_count][7]);
        dev_count++;
        print_usart(USART1, buf);
    }

    while (1) {
        print_usart(USART1, "Bumptss...\r\n");
        presence = owu_reset(&o2);

        i = 10000000;
        while (--i);

        print_usart(USART1, "Convert all\r\n");

        ds_convert_all(&o2);

        i = 50000000;
        while (--i);

        uint8_t j;
        for (i=0; i<dev_count; i++) {
            ds_read_scratchpad(&o2, dev_addr[i], scratch_pad);
            snprintf(buf, 99, "T1=%d, T2=%d, temp=%d\r\n", scratch_pad[0], scratch_pad[1], (scratch_pad[1] << 4) | (scratch_pad[0] >> 4));
            print_usart(USART1, buf);//*/

            snprintf(buf, 99, "Scratch pad %d:", i);
            print_usart(USART1, buf);
            for (j=0; j < 9; j++) {
                snprintf(buf, 99, " %02X", scratch_pad[j]);
                print_usart(USART1, buf);
            }
            print_usart(USART1, "\r\n");
        }

        i = 25000000;
        while (--i);
    }
}

Maždaug taip.

Reklama
Komentarai
  1. Algis parašė:

    aha, pas STM32 galima dar labiau procesoriu atlaisvint ir ta darba perduot DMA daryt, tada DMA pats seks USART registrus ir pades ish daviklio gautus baitus i buferi

    • Antanas parašė:

      Tai galima galima, daug ką galima, jeigu neturima ką veikti. Žinoma, visur reikalingas NASA lygio patikimumas ir efektyvumas – ir ne kitaip.

      • Darau, Blė parašė:

        Na, ko dabar taip sarkastiškai 🙂 Čia gi kaip kitiems kryžiažodžiai, sėmkės ar žvejyba — pomėgis, kuris neturi būti perdėm racionalus. Smagu ištyrinėti, ką daiktas gali, išspausti tą maksimumą. Nu kaip arklys ant asemblerio: very basic, but, boy, can it run!

        • Algis parašė:

          Aha, smagu, kai viskas sukasi optimaliai, i displeju iš buferio duomenys per SPI nuvažiuoja patys, iš ADC kanalu duomenys irgi patys cikle susirenka ir atnaujina masyvus, komunikacja per USART – irgi nurodai buferio pradžia ir paspiri DMA, ir viena syki išsiaiškinus nieko jame nera sudetingo.

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 )

Google+ photo

Jūs komentuojate naudodamiesi savo Google+ 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 )

w

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.