poniedziałek, 25 lutego 2019

Digispark ATtiny85 - czujnik temperatury DS18B20 & wyświetlacz OLED 0,96"

Digispark to platforma rozwojowa na bazie mikrokontrolera ATtiny85. Może być obsługiwana i programowana z poziomu Arduino IDE bezpośrednio przy użyciu kabla USB. Stanowi uzupełnienie dla platform Arduino tam, gdzie liczą się małe wymiary i wykonywane są proste zadania wymagające użycia kilku pinów. Jest przy tym tańsza od swoich większych kuzynów.

Digispark ATtiny85

Funkcjonalność
  • Zasilanie z USB lub zasilacza 7 - 35V
  • Wbudowany stabilizator 5V/500mA
  • Obsługa USB (programowa)
  • 6 linii I/O
    • 3 linie PWM (sprzętowy)
    • 4 linie ADC (wejścia analogowe)
  • 8kB pamięci flash (w tym ok. 2kB zajęte przez bootloader)
  • Interfejs I2C lub SPI z wykorzystaniem USI
  • Diody LED: zasilania i użytkownika (wpięta pod pin P0 lub P1 - zależnie od wersji modułu)

Digispark nie zawiera żadnego układu zajmującego się obsługą USB. Jest to wykonywane software-owo przez wbudowany bootloader o nazwie Micronucleus. Ceną wygody jaką daje to rozwiązanie jest fakt zużycia okołu 1/4 dostępnej pamięci flash, czyli około 2kB. Ponadto zablokowany jest pin RESETu (PB5), co uniemożliwia programowanie ISP (In-System Programming).

Piny platformy (https://www.instructables.com/id/Digispark-Lantern-ATtiny85-Project/)
Piny używane do programowania przez USB (3 i 4) powinny być wolne (niepodłączone do niczego) w trakcie programowania. Po zaprogramowaniu można z nich normalnie korzystać o ile nie ma potrzeby korzystania z połączenie szeregowego, aby np. wysyłać dane na terminal. Ograniczenia platformy opisane są szerzej na wiki produktu i warto się z nimi zapoznać rozpoczynając pracę z modułem.

Schemat elektryczny

Na wstępie pisałem o prostych zadaniach z racji na ilość pamięci i pinów. Z drugiej strony, do biblioteki jest dołączona znaczna ilość przykładów, co z grubsza pokazuje możliwości układu i ułatwia rozpoczęcie z nim pracy. W praktyce bywa ciężko, czego doświadczyłem próbując podpiąć czujnik HC-SR04.

Programowanie

Do korzystania z układu wystarczy kabel microUSB, trzeba jednak wcześniej skonfigurować odpowiednio Arduino IDE i zainstalować odpowiednie sterowniki (z repa Micronucleus). Całość jest opisana na stronach wiki produktu Connecting and Programming Your Digispark.  Ja pobrałem wersję micronucleus-2.0a4-win, natomiast kod pisałem i uruchamiałem na wersji 1.8.7 IDE (wymagana jest wersja 1.6.5+). Na tej wersji zaimportowałem Boards Manager'em obsługę Digisparka'a zgodnie z opisem na wymienonej stronie wiki. Wybrałem platformę "Digispark (Default - 16.5Mhz)". Przy okazji też uruchomiłem programik z tej strony powodujący miganie wbudowanej diody LED. Generalnie w menu File/Examples/Digispark jest wiele ciekawych przykładów. Wybrałem z nich dwa z których w dalszej części artykułu zbuduję prosty monitor temperatury.

Warto wspomnieć jeszcze o repie DigisparkExamplePrograms. W katalogu DigisparkExamplePrograms/Python/DigiUSB są programy typu digiscope.exe czy monitor.exe, które współpracują z Digisparkiem (o ile nie są używane piny odpowiadające z komunikację po USB). Pierwszy program pokazuje wykresy, a drugi, to terminal szeregowy. Przykłady użycia są dostępne w IDE w menu File/Examples/DigisparkUSB. Korzystają one z pliku DigiUSB.h. Jest jeszcze jeden sposób komunikacji po USB przy użyciu pliku DigiCDC.h (File/Examples/DigisparkCDC) i ten ma tę zaletę, że wystarczy już zwykły terminal z pod Arduino IDE.

Sam proces programowania wygląda następująco:
  • po kliknięciu na przycisk Upload pojawia się w panelu informacyjnym (na dole IDE) komunikat: "Running Digispark Uploader... Plug in device now... (will timeout in 60 seconds)" 
  • podłączamy w tym momencie Digisparka i następuje upload kodu (w oknie Panel sterowania\Wszystkie elementy Panelu sterowania\Urządzenia i drukarki na windows 8 pojawia się u mnie ikona nowego urządzenia Digispark Loader)
  • po uploadzie następuje wyjście z bootloadera i uruchomienie wgranego programu na mikrokontrolerze (tym razem w panelu sterowania mam ikonkę z etykietą "Nieznane urządzenie")

Uruchomienie

Wziąłem na tapetę jakiś praktyczny przykład w postaci monitorowania temperatury przy użyciu  czujnika DS18B20 pracującego na magistrali 1-wire. Wynik pomiaru prezentowany jest z kolei na małym wyświetlaczu OLED (sterownik SSD1306) sterowanym po magistrali I2C.

Digispark & OLED & DS18B20

Kod uruchomieniowy to kompilacja kodu z dwóch przykładów dotyczących wymienionych układów. W dodatku maksymalnie okrojona, aby zmieścić kod w ATtiny. Mimo tego i tak zajęcie pamięci sięgnęło 100% (6012 bajtów) ;) Z tego powodu, jak widać w kodzie, zakomentowana jest funkcja sprawdzająca sumę kontrolną. Napotkałem tu dwa problemy, podobnie jak we wcześniejszym projekcie (z czujnikiem HC-SR04). Pierwszy to szybko kończąca się pamięć FLASH, drugi to przeznaczenie pinów. Po pierwsze 1-wire nie chciał działać na pinie P1, pomogło przepięcie się na pin P3. W dostarczonym przykładzie do wyświetlacza OLED zabrakło także informacji na jakich pinach pracuje magistrala I2C co na początku może nie być oczywiste.

Schemat układu uruchomieniowego

Kod z przykładu

#include <DigisparkOLED.h>
#include <OneWire.h>
#include <Wire.h>

OneWire ds(3);
byte addr[8];

void setup() 
{
  oled.begin();
}

void loop() 
{
    byte data[12];
    byte i;

    if (!ds.search(addr)) {
        ds.reset_search();
        delay(250);
        return;
    }

    /*if (OneWire::crc8(addr, 7) != addr[7]) {
        return;
    }*/

    ds.reset();
    ds.select(addr);
    ds.write(0x44, 1);
    delay(1000);
    ds.reset();
    ds.select(addr);    
    ds.write(0xBE);

    for ( i = 0; i < 9; i++) {
      data[i] = ds.read();
    }

    int16_t raw = (data[1] << 8) | data[0];
    byte cfg = (data[4] & 0x60);

    if (cfg == 0x00) raw = raw & ~7;
    else if (cfg == 0x20) raw = raw & ~3;
    else if (cfg == 0x40) raw = raw & ~1;

    oled.clear();
    oled.setCursor(0, 0);
    oled.setFont(FONT8X16);
    oled.print(raw / 16);
    oled.print(".");
    oled.print(raw % 16);
    delay(5000);
}

Z racji na czytelność usunąłem komentarze. Można je znaleźć w przykładach od DS18B20 i OLED.
Jeszcze istotna uwaga - DS18B20 wymaga rezystora podciągającego (4,7k) między wejściem a napięciem zasilania - mój moduł już go posiadał. Stąd jego brak na schemacie połączeń.

Dalsze prace z Digispark'iem

Do wielu zastosowań z pewnością wystarczy platforma dostarczona z dobrodziejstwem inwentarza. Po to właśnie została opracowana, aby jak najwygodniej się na niej pracowało. Jeśli jednak chcemy poeksperymentować lub dostać dodatkowe cenne miejsce zajmowane przez bootloader, konieczna jest głębsza ingerencja. I tak można na przykład można chcieć:

Źródła
1) Strona wiki digispark
2) Forum digispark
3) Konfiguracja Arduino IDE

2 komentarze:

  1. Bardzo fajnie napisane. Pozdrawiam serdecznie !

    OdpowiedzUsuń
  2. Skecz wydaje się zbyt duży: Sketch uses 6024 bytes (100%) of program storage space. Maximum is 6012 bytes.
    Wchodzi dopiero po usunięciu wyświetlania dziesiątej części odczytu.
    Czy można jakoś powiększyć czcionkę, aby zajmowała cały display? używam oled 32x128

    OdpowiedzUsuń