Digispark (klon): prosty robot mobilny

W świecie płytek typu Arduino, łatwo jest realizować pojedyncze doświadczenia. Mruganie diodami, kilkakrotne obrócenie serwem, bipniecie buzzerem – do podstawowych eksperymentów wystarczy garść kabelków połączeniowych i kilka linijek kodu.

„Schody” zaczynają się, gdy chcemy zrealizować jakieś konkretne zadanie, która wymaga połączenia kilku bloków funkcjonalnych.  Wtedy wychodzą na jaw problemy z zasilaniem, dogadywaniem się niektórych elementów, poziomami logiki, niewystarczającą liczbą pinów oraz „hackami” w bibliotekach.

Dlatego właśnie postanowiłem sprawdzić klona Digisparka w warunkach bojowych.

fuselage_3

Cel…

…skonstruowanie małego i taniego robota mobilnego, na częściach popularnie dostępnych na rynku. 3-punktowe podwozie, 2 silniki elektryczne (lub serwa 360), zasilany z baterii, zdalne sterowanie za pomocą pilota na podczerwień. Szkielet kombinowany z czego popadnie – głównie metalowe klocki konstrukcyjne i lego.

Jednostka centralna…

Będziecie potrzebować:

  • Digispark z bootloaderem micronucleus
  • Kabel microusb do programowania

…klon Digisparka. Mimo wielu problemów, jakie niesie ze sobą to urządzonko, myślę że zadziała.

Już wiem, że połączenie USB jest raczej kapryśne. Czasami przeprogramowanie układu wymaga kilkukrotnego włożenia-wyciągniecia z portu USB  komputera. Aktywny hub niewiele tu pomaga.

Szkice czasem tylko udają, że się ładują, bootloaderowi zdarza się zniknąć a piny nie zawsze działają zgodnie ze swoim przeznaczeniem… Brzmi jak wyzwanie, nieprawdaż?

Środowisko programowania…

Będziecie potrzebować:

  • Arduino IDE z zainstalowanym wsparciem dla Digispark (pod Windows lub Linux)

…Arduino IDE 1.5.8 dla linux 64-bit (MINT 17.3), zmodyfikowane dla Digisparka. Dlaczego to? Digispark, którego używam do tego projektu, swego czasu się zbuntował i konieczne było przeflaszowanie bootloadera (zobacz; Digispark i micronucleus: crach).  Niestety okazało się, że najnowsze Arduino IDE (1.6.6) pobrane ze strony arduino.cc, rozszerzone o wsparcie dla Digispark (zobacz: Digispark: jak zacząć pod Windows), nie obsługuje wersji micronucleus 2.+ – akurat tej, która jest dostępna na githubie Digistump.  Użyłem więc starszej wersji środowiska, udostępnianej przez Digispark.

Dodatkowe narzędzia…

W trakcie rozwijania i testowania przydadzą się:

  • Konwerter UART2USB (+Putty na hoście), z kablem USB
  • Programator ISP, np. USBASP2
  • Analizator logiczny
  • Oscyloskop
  • Multimetr

Niestety, z Digisparkiem nie zawsze wszystko idzie zgodnie z planem. Oczywiście idealną pomocą jest oscyloskop – ale to dość kosztowna „zabawka”. Alternatywnie polecam np. analizator logiczny. Podstawowe modele można kupić za bardzo rozsądne pieniądze.

Dodatkowo przyda się przejściówka USB2UART. Dzięki niej będziecie mogli użyć biblioteki SoftSerial do przesyłania logów z Digisparka. Więcej dowiecie się tutaj: Digispark: port szeregowy UART.

IMG_20160209_112101Budowa

Będziecie potrzebować:

  • Materiały do konstrukcji podwozia – kółka, klocki konstrukcyjne, lego
  • Płytkę stykową, do osadzenia wszystkich elementów
  • Pojemnik na baterie
  • Paski plastykowe do spinania elementów (tralki)
  • Recepturki, taśmę klejącą dwustronną

Jeden z prototypów...
Jeden z prototypów…

Swoje roboty najczęściej buduję z metalowych klocków konstrukcyjnych. Swego czasu byłem nawet w ich muzeum w Police nad Metui – niektórzy czytelnicy na pewno kojarzą firmę Merkur. Ale i w Polsce mamy ciekawych producentów – np. firmę Alexander i jej serię Mały Konstruktor. Na podstawie ich kompletu raz zbudowałem całkiem fajną ciężarówkę:

Oczywiście bardzo lubię też lego – które łatwo łączą się z np. serwami.

Do konstruowania robotów często wykorzystuję tzw. drewo cytrusowe. Pochodzi ze… skrzynek na owoce wyproszonych z okolicznego warzywniaka. Część z nich jest zrobiona ze zwykłej dykty, ale niektóre z 3mm sklejki – bardzo lekkiej i łatwej w obróbce (wystarczy nóż segmentowy).

Do montażu stosuję też paski plastykowe (tzw. tralki), dwustronną taśmę klejącą, recepturki – co tam podpadnie pod rękę.

Silniki

Będziecie potrzebować:

  • Silniki albo serwa 360 zasilane na 4-6V
  • Najlepiej takie wyposażone w przekładnie – 100obr/min to już dość rozsądna szybkość.

Do napędu mojego robocika planowałem użyć tanich silników RF-300A. Oryginalnie wykorzystywane są w napędach CD/DVD. Można je zasilać napięciem 3-6V. Na biegu jałowym zużywają 22mA, a przy zatrzymaniu wału maksymalnie 390mA.

Silniczki RF300A
Silniczki RF300A

Właściwie to kupiłem je głównie dlatego,  że były tanie (ok. 5PLN/szt). Niestety okazały się za słabe. Przy ciężarze 4-rech baterii AA, 2 silniki mogły uciągnąć prototyp tylko na pełnej mocy, jedynie na wprost i po kafelkach – o jeździe po dywanie czy skręcaniu jednym silnikiem nie było mowy.

Generalnie skręcanie silnikami bez-przekładniowymi jest dość dyskusyjne.

Inną opcja mogą być mini-silniczki z przekładniami, np. polulu. To świetne rozwiązanie. Takie napędy są naprawdę bardzo trwałe i dają niesamowity ciąg. Niestety… kosztują konkretne pieniądze.

Tutaj zastosowałem 2 serwa 360st. Dokładniej są to zmodyfikowane Redoxy s90. Ze względu na sposób wykonania modyfikacji, steruje się nimi jak zwykłymi silnikami kluczując zasilanie sygnałem PWM.

Przerobienie „normalnego” serwa na 360 nie jest takie trudne: modyfikacja serwa towrprosg90 na 360st.

Serwa przymocowałem do kasty za pomocą 2 tralek. Użyłem też kółek lego – łatwo je przymocować do krzyżakowych orczyków serwa.

fuselage_0Sterowanie silnikami: tranzystory

Będziecie potrzebować:

  • Tranzystory NPN, np. TIP122
  • Rezystory bazowe – w zależności od silników i tranzystorów

Z każdego z serw wychodzą 2 kabelki. Jeżeli podłączymy je po prostu do + i masy zasilania – nie będziemy mieli żadnej możliwości sterowania nimi. Oczywiście nie możemy też podłączyć kabelków bezpośrednio do AtTiny85 – pobór prądu z silników by je usmażył.

Dlatego podłączymy je inaczej: jeden kabelek silniczka do „+” zasilania, a drugi – przez tranzystor do masy. Podłączając kabelek od silnika do kolektora tranzystora, którego emiter łączymy z masą, będziemy mogli sterować przepływem prądu przez silnik. Tranzystor w stanie nasycenia, sterowany przez sygnał PWM podawany na bazę, będzie zachowywał się jak przełącznik. Włączając i wyłączając prąd (zgodnie z sygnałem PWM), będziemy sterować szybkością obrotową silników.

Pozostaje wybrać tranzystor. Kilka NPN znalazłem w szufladzie:

Zacznijmy od Ic – maksymalnego prądu, jako może przepłynąć przez złącze kolektor-emiter. Zablokowane serwo pobierze nawet 500mA. Ic dla 2n2222 to 600mA – trochę za blisko granicy. TIP122 to 5A (wow!). bc547 – tylko 100mA, więc odpada ze stawki. bd139 ma Ic na poziomie 1.5A – też się nada.

Teraz sprawdzimy jaki prąd Ib musi popłynąć przez złącze baza-emiter, żeby tranzystor się nasycił. W przypadku bd139:

BD139 (pobrano z instrukcji
BD139 (pobrano z instrukcji

Widać to, że:

I_{c} = 10 \cdot I_b

Czyli, żeby wygenerować 500mA, potrzebowalibyśmy prądu bazy 50mA. To znacząco za dużo dla AtTiny.

W instrukcji do TIP122 znajdziecie wykres 2.

Tip122 - nasycenie (pobrano z instrukcji)
Tip122 – nasycenie (pobrano z instrukcji)

Widać na nim, że:

I_{c} = 250 \cdot I_b

Stąd dla 500mA, minimalny prąd bazy to 2mA. AtTiny wyrobi się bez problemu.

Z powyższego wykresu widać jeszcze jedno: napięcie Vbe nasycenia dla prądu 0.5A to ok. 1.4V. Informacja ta będzie nam potrzebna do wyznaczenia rezystora bazy R_b. Skoro zasilanie bazy będzie 5V, na złączu baza-emitor spadek wyniesie 1.4V, spadek napięcia na rezystorze musi wynieść 3.6V. Stąd:

I = {U \over {R_b}}, {R_b} = {U \over I }= {3.6 \over 0.002}=1750 \Omega

Rezystor 1750Ω powinien dać radę – ja użyję mniejszego (1kΩ), który da większy prąd bazy gwarantując nasycenie.

TIP122 (pobrano z instrukcji)
TIP122 (pobrano z instrukcji)

Podłączenie:

transistor_0aTranzystory zamontowałem na płytce stykowej i podłączyłem do Digispark’a:

Tranzystory TIP122
Tranzystory TIP122

Zauważcie, że bazy tranzystorów podłączyłem do pinów P1 i P4 Digisparka.

Oczywiście w ten sposób będę mógł jedynie włączać/wyłączać silniki oraz regulować ich szybkością obracania się tylko w jedną stronę. Możliwość odwracania biegu dają dopiero układy takie jak L293D.

Zasilanie

Będziecie potrzebować:

  • Baterii lub akumulatorów – np. 4xAA, 2×14500
  • Pudełka na akumulatory/baterie – najlepiej z wyłącznikiem
  • LM78S05 (jeżeli napięcie akumulatorów, baterii > 6v)
  • Jeżeli LM78S05: kondensatorów 0.33uF i 0.1uF (330 i 100 nF, oznaczenia 334 i 104)
  • Kabelki połączeniowe – męsko-męskie i męsko-żeńskie

Serwa wymagają zasilania ok. 4-6V. Z początku planowałem użyć pojemnika z 4-ma bateriami AA. Niestety baterie te – choć łatwo dostępne, dość dużo ważą. Postanowiłem zamienić je na 2 akumulatory z serii 14500. To bardzo ciekawe ogniwa. Mają rozmiar paluszków AA – a każda daje napięcie ok. 3.7 (naładowane nawet 4.3). Wystarczą więc tylko 2 połączone szeregowo.

Akumulatory LiIon - typ 14500, 3,7V
Akumulatory LiIon – typ 14500, 3,7V

Nie ma jednak nic za darmo: naładowane akumulatory dają razem nawet ponad 8 woltów. Taki poziom napięcia mógłby uszkodzić napędy. Potrzebny jest więc dodatkowy stabilizator. Prosty LM78S05 powinien wystarczyć. Daje 5V na wyjściu przy maksymalnym prądzie 2A. Koszt ok. 1,5 PLN.

LM78S05 (pobrane z instrukcji)
LM78S05 (pobrane z instrukcji)

Model „s” może przewodzić 2x więcej prądu od wersji 7805. Wydawało mi się to bezpiecznym marginesem.

W jaki sposób podłączyć ten stabilizator? Instrukcja podaje tak:

lm_0Nie miałem pod ręką kondensatora 330nF – użyłem 220nF – też powinien być ok. Podłączyłem wszystko na płytce stykowej:

fuselage_4

Odpowiednie umieszczenie pudełka z bateriami umożliwia też użycie jego przełącznika do włączania/wyłączania robota:

fuselage_5Zdalne sterowanie

Będziecie potrzebować:

  • Pilota na podczerwień
  • Diodę IR odbiorczą, np. TSSOP2238,
  • Kondensator elektrolityczny ok. 4.7uF, podłączony między Vcc i GND

Do zdalnego sterowania robotem użyłem podczerwieni: zestawu pilot – dioda odbiorcza IR. Raczej nie próbujcie walczyć z diodą IR bez kondensatora między zasilaniem a masą. Będziecie dostawać przedziwne wyniki. Kolejne wciśnięcia tego samego klawisza będą dawać inne kody.

Podłączenie jest bardzo proste:

TSOP22... (pobrane z instrukcji)
TSOP22… (pobrane z instrukcji)

Zasilanie Vcc podłączom do 5V (wyjście z 78S05), masę do masy, a pin OUT do P2 Digisparka.

ir_2Jeżeli chodzi o samego pilota – chwyciłem co leżało pod ręką – akurat zgrabny pilot od radiomagnetofonu sony.

W przypadku tego czujnika, bardziej skomplikowane jest samo oprogramowanie. Najpierw do nowego projektu dodajcie bibliotekę: DigisparkIrLib. W kodzie pojawią się dodatkowe nagłówki:

#include <IRLibTimer.h>
#include <IRLibMatch.h>
#include <IRLib.h>
...

Biblioteka DigisparkIrLib wymaga drobnej modyfikacji. Odnajdźcie plik w katalogu Arduino IDE: ./hardware/digistump/avr/libraries/DigisparkIRLib/IRLib.h i zmieńcie linijkę:

#define MY_IR_PROTOCOL ...

Tak, żeby określała rodzaj Waszego pilota; u mnie:

#define MY_IR_PROTOCOL PROTO_SONY

Najczęściej:

#define MY_IR_PROTOCOL PROTO_NEC

Takim protokołem posługuje się np. pilot keyes:

Keyes IR
Keyes IR

Dekoder przetworzy tylko sygnały z protokołu, który wybierzecie; tzn. jeżeli podacie:

#define MY_IR_PROTOCOL PROTO_SONY

…biblioteka zdekoduje sygnały z pilota sony, ale nie keyes’a (który posługuje się protokołem nec’a). Generalnie możnaby włączyć wszystkie znane protokoły:

#define MY_IR_PROTOCOL ALL_IR_PROTOCOL

…ale wtedy kod rozrośnie się tak, że nie zmieści się w AtTiny.

Biblioteka DigisparkIrLib wczytuje sygnał ze wskazanej linii IR i umieszcza go buforze. Bufor ten przetwarza dekoder. Dekoder używa MY_IR_PROTOCOL żeby poprawnie zinterpretować zawartość bufora. W przypadku poprawnego rozpoznania, dostaniecie liczbę (typu long), inną dla każdego przyciśniętego klawisza.

Teraz będziecie musieli określić, jakie kody generują się po wciśnięciu klawiszy na pilocie. Pomoże Wam taki program:

#include <IRLibTimer.h>
#include <IRLibMatch.h>
#include <IRLib.h>
#include <SoftSerial.h>
#include <TinyPinChange.h>
//On basis of Digistump examples
//IR output connected to P2
#define IR_PIN 2

IRrecv My_Receiver(IR_PIN);
IRdecode My_Decoder;


//Softserial connectected to 0,1 (RX, TX)
SoftSerial sserial(0,1);

void setup() {
  sserial.begin(9600);
  My_Receiver.enableIRIn();
}
 
void loop() {
  if (My_Receiver.GetResults(&amp;amp;My_Decoder))
  {
    //decode received rawBuffer
    My_Decoder.decode();
    //make sure you only look at your type of remote control
    if ( My_Decoder.decode_type == PROTO_SONY )
    {
       sserial.print( My_Decoder.value );
       sserial.println();
    }
    My_Receiver.resume();
   }
}

Podłączcie RX przejściówki USB2UART do pinu P1 i wciskajcie przyciski na pilocie – na konsoli hosta zobaczycie kolejne kody klawiszy.

Oprogramowanie

Oprogramowanie jest niezbyt skomplikowane. Oprócz DigisparkIrLib, sketch wymaga dodania biblioteki  DigisparkTinySoftPwm.

Znając kody klawiszy, sam program nie jest już zbyt trudny:


#include <TinySoftPwm.h>
#include <IRLibTimer.h>
#include <IRLibMatch.h>
#include <IRLib.h>

//Define pins
#define PIN_LEFT 4
#define PIN_RIGHT 1
#define IR_PIN 2

//Define PWMs
#define ENGINE_STOP 0
#define ENGINE_MAX 255
#define SPEED_STEP 5

//Variables controlling PWM for each engine
int speedMeL = ENGINE_STOP;
int speedMeR = ENGINE_STOP;

//IR instance
IRrecv My_Receiver(IR_PIN);
IRdecode My_Decoder;

void setup() {
  My_Receiver.enableIRIn();
  pinMode(PIN_LEFT, OUTPUT);
  pinMode(PIN_RIGHT, OUTPUT);
  TinySoftPwm_begin(128, 0);
}

void loop() {
  //Taken from TinySoftPWMDemo: process PWM timers
  static uint32_t StartUs = micros();
  if ((micros() - StartUs) &amp;amp;amp;gt;= 60)
  {
    StartUs = micros();
    TinySoftPwm_process();
  }
  //Get results from decoder
  if (My_Receiver.GetResults(&amp;amp;amp;amp;My_Decoder))
  {
    //decode received rawBuffer
    My_Decoder.decode();
    //make sure you only look at your type of remote control
    if ( My_Decoder.decode_type == PROTO_SONY )
    {
      int key_value = My_Decoder.value;
      switch (key_value) {
        case 21538://operate button
          break;

        case 28962://function button
          break;

        case 31526://band button
          break;

        case 26150://play button
          speedMeL = ENGINE_MAX;
          speedMeR = ENGINE_MAX;
          break;

        case 3622://stop button
          speedMeL = ENGINE_STOP;
          speedMeR = ENGINE_STOP;
          break;

        case 24870://left button
          speedMeL = ENGINE_MAX;
          speedMeR = ENGINE_STOP;
          break;

        case 4390://right button
          speedMeL = ENGINE_STOP;
          speedMeR = ENGINE_MAX;
          break;

        case 9250://volup button
          speedMeL += SPEED_STEP;
          speedMeR += SPEED_STEP;
          break;

        case 25634://voldown button
          speedMeL -= SPEED_STEP;
          speedMeR -= SPEED_STEP;
          break;
      }
      if (speedMeL < ENGINE_STOP )speedMeL = ENGINE_STOP;
      if (speedMeR < ENGINE_STOP )speedMeR = ENGINE_STOP; if (speedMeL > ENGINE_MAX )speedMeL = ENGINE_MAX;
      if (speedMeR > ENGINE_MAX )speedMeR = ENGINE_MAX;
      
      TinySoftPwm_analogWrite(PIN_LEFT, speedMeL);
      TinySoftPwm_analogWrite(PIN_RIGHT, speedMeR);
       
    }
    //Make receiver listen to a next code
    My_Receiver.resume();
  }
}

Biblioteka IR wczytuje i dekoduje kody z pinu P2. Jeżeli wciśnięto klawisz play na pilocie, na P1 i P4 generowany jest sygnał PWM, który uruchamia silniki. Wciśnięcie stop je zatrzymuje. W przypadku skręcania – zatrzymuję jeden silnik i kręcę drugim.

To oczywiście bardzo prosty algorytm – możecie go ulepszyć!

Efekty

Tak jeździ:

I kilka fotek:

shot_0 shot_1 shot_2Podsumowanie

No i udało się: robot reaguje na pilota, jeździ po dywanie – od biedy można by dołączyć do niego jeszcze kilka detali.

Podczas całej budowy okazało się, że największym problemem są… biblioteki. A dokładniej ich niepełna – i raczej nastawiona na programistów, niż użytkowników – dokumentacja. Trochę trzeba się naczytać kodu, żeby dowiedzieć się, że IR używa dodatkowego timera – blokując w ten sposób pin P0.

Sam Digispark też nie pomaga – pin P3 jest uruchamiany przez bootloader szukający hosta. Jeżeli podłączycie do P3 silnik – przy starcie czipu zacznie on działać… P5 to reset – podanie na niego stanu niskiego, spowoduje zresetowanie Digisparka. Właściwości te opiszę w kolejnych tekstach z serii.

Źródła

Jeden komentarz do “Digispark (klon): prosty robot mobilny”

Dodaj komentarz