Mikrokontrolery - Jak zacząć?

... czyli zbiór praktycznej wiedzy dot. mikrokontrolerów.

poniedziałek, 21 marca 2011

Silnik krokowy sterowany za pomocą mikrokontrolera ATmega16


Autor: TPT
Redakcja: Dondu

Schemat sterownika unipolarnego silnika krokowego by TPT.
Główną zaletą silników krokowych jest możliwość dokładnego sterowania kątem obrotu bez użycia dodatkowych elementów takich jak np. enkodery. Dzięki temu są szeroko stosowane w przeróżnych układach mechatronicznych – drukarki, napędy CD/DVD, przeróżne sterowniki w samochodach, itd., itp..

Najczęściej w tego typu układach stosowane są dwufazowe silniki krokowe, więc takimi też się zajmiemy. Każdy, kto zajmuje się elektroniką na pewno ma dostęp do np. starej drukarki, więc nie jest ciężko zdobyć mały silnik krokowy, przez co można wykorzystać go do amatorskich projektów mechatronicznych.

Ponieważ z mojego doświadczenia wynika, że częściej w tego typu małych układach wykorzystywane są dwufazowe silniki unipolarne niż bipolarne, więc pomęczymy właśnie unipolarny silnik wyciągnięty z drukarki HP.

Czym się różni silnik bipolarny od unipolarnego? W dużym skrócie: silnik unipolarny posiada 5 lub 6 przewodów, sterujemy nim puszczając prąd przez jego uzwojenia zawsze w jednym kierunku. W silniku bipolarnym polaryzacje na uzwojeniach zmienia się, z reguły posiada 4 wyprowadzenia.

Więcej o silnikach krokowych (budowa, zasady sterowania, wady i zalety) można poczytać tutaj:

Silniki unipolarne (jak już wspomniałem) posiadają 5 lub 6 wyprowadzeń, z czego jedno (dla 5. wyprowadzeń) lub dwa (dla 6. wyprowadzeń) są zasilaniem silnika. Można je wyznaczyć za pomocą omomierza, środek uzwojenia (oznaczany jako COMA/COMB) ma najmniejszą rezystancję. W moim przypadku między końcówkami uzwojeń rezystancja wyniosła 150Ω, między zasilaniem/końcówką 75Ω.

W przypadku silników z pięcio-przewodowymi wyprowadzeniami mamy zadanie utrudnione, gdyż przewód zasilający jest wspólny, więc nie ustalimy tą metodą par uzwojeń, ale to już można ustalić w czasie podłączania do sterownika (jeśli silnik będzie się wiercił w lewo i w prawo to będzie oznaczało, że podłączyliśmy źle).

Aby sprawdzić, czy silnik jest sprawny i nadaje się do użytku można zbudować sterownik "mechaniczny" - cztery switche (#1 - #4), które będą zwierać końcówki uzwojeń z GND, COM podłączamy do zasilania. Naciskając po kolei switche obracamy wałem, jeśli podłączymy końcówki w odpowiedniej kolejności naciskając przyciski w sekwencji #1 do #4 będziemy obracali wałem ciągle w jedną stronę, jeśli nie- podłączenie jest złe. Jeśli zaś silnik w ogóle nie reaguje - prawdopodobnie silnik jest uszkodzony.

Do sterowania wyżej wspomnianym silnikiem wykorzystałem ATmega16 (z wewnętrznym generatorem 8MHz) wraz z dedykowanym sterownikiem silników krokowych, popularnym układem L297 oraz N- MOSFET-y BS170 (0,3A).

Oczywiście sterowników silników krokowych jest więcej, wybrałem L297 ze względu na jego wszechobecność w sklepach elektronicznych. Zamiast MOSFET-ów można użyć tranzystorów bipolarnych w układzie Darlingtona (stosując np. układ U2003).

Po zapoznaniu się z dokumentacją przystąpiłem do podłączenia układu na płytce stykowej zgodnie ze schematem poniżej.

Schemat sterownika unipolarnego silnika krokowego
Schemat sterownika unipolarnego silnika krokowego.

Rezystory R2-4-6-8 są po to, aby wymusić tzw. polaryzację zamykającą, dzięki czemu unikniemy niekontrolowanego włączenia tranzystora (w naszym przypadku zakłócałoby to pracę silnika). Więcej na ten temat znajdziesz w artykule: Tranzystor MOSFET: Wiedza tajemna.

Diody LED włożyłem aby było widać gdzie jest w danym momencie sygnał (do tego efektownie to wygląda oraz, jak wiadomo, człowiekowi zawsze lepiej na duszy, gdy się mu coś zaświeci).

Z ciekawszych wejść układu L297:

  • ENABLE - po podaniu na nie zera logicznego blokujemy prąd płynący przez silnik
  • DIRECTION - w zależności od stanu logicznego podanego na ten pin kręcimy wałem w lewo lub prawo (w zależności od podłączenia silnika)
  • CLOCK - sterowanie kolejnymi krokami silnika. Silnik wykonuje krok w chwili pojawienia się narastającego zbocza sygnału (jeden sygnał = jeden krok).
  • HALF/FULL - stan wysoki, to sterowanie półkrokowe (dwukrotnie większa rozdzielczość), stan niski, to sterowanie pełnokrokowe.


Oryginał na koncie autora: Unipolar Stepper Motor Controller


Do moich testów dorzucam często wyświetlacz LCD oraz diody kontrolne, w tym przypadku:

  • niebieska - pokazuje kiedy pojawia się sygnał podawany na wejście CLOCK, pokazuje też częstotliwość podawania
  • czerwona - włączenie podawania sygnału 
  • zielona i żółta - kierunek obrotu. 

Dzięki temu układ staje się czytelniejszy, a tak poza tym to nie ukrywam - lubię świecące zabawki :-)

Program jaki napisałem do moich testów znajduje się poniżej. Jak można było się dowiedzieć z odnośnika podanego wyżej - silniki krokowe są (stosunkowo) wolnoobrotowe, maksymalna częstotliwość z jaką udało mi się sterować silnikiem wyniosła 31250Hz. Przy większej częstotliwości silnik jedynie „wiercił” się.

W poniższym programie prędkość ustawiamy w warunku if-a przy komentarzu //SPEED (im większy parametr cnt2, tym mniejsza prędkość).

Wyświetlacz wykorzystany przeze mnie zgodny z HD44780.

Program służył tylko i wyłącznie do testów i służył do kręcenia silnikiem w lewo i prawo.

/* TEST krokowca (pod unipolarny)
// TPT
// mega16+LCD
// mLCD (C0-C5)
// 14.07.2013
// aktualizacja 17.07.2013
// stan:OK!!!
//
// UWAGA!!!
// W pliku HD44780.h należy zdefiniować piny, do których podłączysz LCD.
*/

//#define F_CPU 8000000UL  //Program dla 8MHz. Ustaw w opcjach projektu lub
                           //usuń znaki komentarza

#include <avr/io.h>
#include <avr/interrupt.h>

#include "HD44780.h"

#define SW1 PD6
#define SW2 PD5
#define SW3 PD4
#define DIR PD3
#define LEDG PB0
#define LEDY PB1
#define LEDR PB2
#define CLOCK PD2

volatile unsigned int i=0; // ON/OFF
volatile unsigned int j=0; // Direction

volatile unsigned int cnt  = 0;
volatile unsigned int cnt2 = 0;

// Zmienne do kontroli przycisków
uint8_t oldkey[2];
uint8_t key[2];


//*****************************************************************

void io_init(void){ //Ustawienia pinów

     //atmega16
     DDRA |= 0b00000000;
     DDRB |= 0b00000111;
     DDRD |= 0b10001100;

     //Pull Up-y
     PORTD |= (1<<SW1) | (1<<SW2) | (1<<SW3);

     i=0;
     cnt=0;
}

//*****************************************************************

void timer_init(void)
{
     TIMSK |= (1<<TOIE0); //Włącz przerwanie overflow (przepełnienie timera)  
     TCCR0 |= (1<<CS01) | (1<<CS00); //preskaler
}

//*****************************************************************

void left (void) // Kręcenie w lewo  
{
 PORTD &= ~(1<<DIR);
 PORTB |= (1<<LEDG);
 PORTB &= ~(1<<LEDY);
}

//*****************************************************************

void right (void) // Kręcenie w prawo  
{
 PORTD |= (1<<DIR);
 PORTB &= ~(1<<LEDG);
 PORTB |= (1<<LEDY);
}

//*****************************************************************

void defaultThis() // Reset  
{
 PORTB &= ~(1<<LEDG);
 PORTB &= ~(1<<LEDY);
 PORTB &= ~(1<<LEDR);
 PORTD &= ~(1<<CLOCK);
}

//*****************************************************************

void lcd_layout(void) // Obsługa LCD  
{
 LCD_Clear();
 LCD_GoTo(0,0);
 
 if (i == 1)
 {
  LCD_WriteText("Engine: OFF");
  LCD_GoTo(0,1);
  LCD_WriteText("Direction: OFF");
  defaultThis();
 }
 
 if ((i == 2) && (j == 0))
 {
  LCD_WriteText("Engine: ON");
  LCD_GoTo(0,1);
  LCD_WriteText("Direction: LEFT"); 
 }
 
 if ((i == 2) && (j == 1))
 {
  LCD_WriteText("Engine: ON");
  LCD_GoTo(0,1);
  LCD_WriteText("Direction: RIGHT"); 
 } 
}

//*****************************************************************

void readButtons() // Obsluga przycisków  
{
 oldkey[0] = 1;
 oldkey[1] = 1;
 oldkey[2] = 1;
 
 key[0]= PIND & (1<<SW1);
 key[1]= PIND & (1<<SW2);
 key[2]= PIND & (1<<SW3);
 
 if((key[0]^oldkey[0]) && (key[0]==0))
 {
  j=0;
  left();
  lcd_layout();
 }
 
 if((key[1]^oldkey[1]) && (key[1]==0))
 {
  j=1;
  right();
  lcd_layout();
 }
 
 if((key[2]^oldkey[2]) && (key[2]==0))
 {
  if (i == 1)
  {
   i = 2;
   lcd_layout();
   OCR2 = 0;
   PORTB |= (1<<LEDR);
   
   if ( j == 0 )
   {
    PORTB |= (1<<LEDY);
    PORTB &= ~(1<<LEDG);
   }
   if ( j == 1 )
   {
    PORTB |= (1<<LEDG);
    PORTB &= ~(1<<LEDY);
   }
  }
  else
  {
   i = 1;
   lcd_layout();
   OCR2 = 255;
  }
 }
}


//*****************************************************************

int main (){  //Początek programu

 io_init();
 timer_init();

 LCD_Initalize();

 sei();

 LCD_GoTo(0,0);
 LCD_WriteText("TEST KROKOWCA");
 LCD_GoTo(0,1);
 LCD_WriteText("MIKROKONTROLERY");

 i=1;
 while (1) {
  //pętla główna
 }
}

//*****************************************************************

ISR(TIMER0_OVF_vect)//przerwanie po przepełnieniu timera 
{
 cnt++;
 if (cnt == 100) //eliminacja drgań styków
 {
  readButtons();
  cnt=0;
  }
 if( i == 2)
 {
  cnt2++;
  if (cnt2 == 50) // SPEED
  {
   PORTD ^= (1<<CLOCK);
   cnt2=0;
  }
 }
}

Do pobrania kompletny projekt AVR Studio 4.18: SILNIK_1.zip (kopia)

W przypadku pytań chętnie odpowiem.
Pozdrawiam,
TPT

Oceń artykuł.
Wasze opinie są dla nas ważne, gdyż pozwalają dopracować poszczególne artykuły.
Pozdrawiamy, Autorzy
Ten artykuł oceniam na:

24 komentarze:

  1. Silnik skokowy. Mówienie czy pisanie ,,silnik krokowy" to błąd wynikający z bezpośredniego tłumaczenia z angielskiego, podobnie jak ,,scena zbrodni" zamiast ,,miejsce zbrodni";)

    OdpowiedzUsuń
    Odpowiedzi
    1. Wikipedia nie jest wyznacznikiem. Według normy jest ,,skokowy". Ja wiem, że przyjęło się potocznie mówić ,,krokowy", ale jak już pisać, to wersję poprawną;)

      Usuń
    2. W latach 80-tych kiedy pobierałem nauki w EZN Wrocław przy Elwro, pracując później w dziale konstrukcyjnym Elwro, wszelkie silniki tego typu w książkach, skryptach uczelnianych i politechnicznych, dokumentacji przemysłowej oraz produkowanych przez Elwro urządzeń, były zwane krokowymi. I tego się trzymam do dzisiaj :-)

      Usuń
    3. A tak już humorystycznie, to obie nazwy są równie trafne, bo silnik ani nie skacze, ani nie kroczy :-) Ale dobrze, że zwróciłeś uwagę na fakt, iż stosowana jest także inna nazwa.

      Usuń
    4. Z drugiej strony sterując silnikiem tego typu przechodzimy przez kolejne kroki (a nie skoki) komutacji. W dodatku nie Polacy wymyślili ten typ silnika, więc dosłowne tłumaczenie w tym przypadku nie jest złe. No i IMHO w tym silniku nic nie skacze, więc nazwanie go skokowym jest co najmniej humorystyczne.

      Usuń
    5. Ja tylko mówię, co obecne normy mówią. A czy to mądre czy głupie to już inna kwestia. Dla mnie określenie ,,krokowy" jest też trafniejsze, ale co ja mogę?;)

      Usuń
  2. Czepianie się. Spróbuj znaleźć w google sklepy handlujące silnikami skokowymi, a spróbuj silnikami krokowymi. Jak widać, wśród ludzi zajmujących się tematem czy używających tych silników nazwa silnik krokowy się tak przyjęła, że ciężko będzie to teraz odwrócić :)

    OdpowiedzUsuń
  3. Witam,

    Super projekcik.
    Czy jest szansa, żeby autor dodał do schematu informacje o podłączeniu wyświetlacza i mikrokontrolera? Tak, żeby mniej ogarnięci (czytaj, chociażby ja sam) mogli coś takiego podłączyć i zakręcić tym krokowcem? Czym by się różnił sterownik dla silnika bipolarnego?
    Serdecznie pozdrawiam,
    tonyx2

    OdpowiedzUsuń
    Odpowiedzi
    1. Witam,

      Dzięki za słowa uznania.
      Odnośnie podłączenia mikrokontrolera, jest informacja o tym na samym początku programu:
      "
      #define SW1 PD6
      #define SW2 PD5
      #define SW3 PD4
      #define DIR PD3
      #define LEDG PB0
      #define LEDY PB1
      #define LEDR PB2
      #define CLOCK PD2
      "
      takim sposobem pod nazwą np. "CLOCK" mam pin PD2, i tak np.:
      PORTD ^= (1<<CLOCK); powoduje zmianę stanu pinu PD2 na przeciwny.
      Skróty używane przeze mnie: SW- switch- przycisk, LED(R,G,Y)-dioda odpowiedniego koloru, DIR i CLOCK- są to również przyciski odpowiedzialne kolejno: za zmianę kierunku obrotu oraz za przesył impulsów powodujących kolejne kroki silnika.

      Usuń

    2. Odnośnie podłączenia LCD: w linijce:
      "// mLCD (C0-C5)"
      zawarłem w skrócie informacje o podłączeniu wyświetlacza (informacji na temat podłączenia oraz bibliotek do obsługi jest w internecie multum), mianowicie w moim przypadku było to: PC0=> RS, PC1 => E, PC2-PC5 => DB4-7

      Czym by się różnił sterownik dla silnika bipolarnego- otóż jak wspomniałem, w silniku bipolarnym polaryzację na uzwojeniach zmienia się, a więc poza sterownikiem potrzebujemy poza sterownikiem elementu, który zrealizuję zmianę tej polaryzacji - takim elementem jest oczywiście mostek H. W przypadku układu l297 dobrym pomysłem będzie zastosowanie scalonego mostka H => l298. Na pierwszej stronie dokumentacji l297 masz schemat własnie sterownika dla silnika bipolarnego z mostkiem l298.
      Pozdrawiam

      Usuń
  4. a jak z zasilaniem tego silniczka ?
    ja mam dwa krokowce z drukarki jeden na 24VDC i drugi na 12VDC
    z zasilaczy jakie posiadam do 18 VDC od laptopa i 5VDC od telefonu
    Jak by pan widzial moziwosc zasilanie silniczków w moim przypadku

    OdpowiedzUsuń
  5. Witam
    Ten na 12VDC mógłbyś zasilić np. poprzez ten zasilacz z laptopa z jakimś mocnym stabilizatorem na 12V (taki, który wytrzyma ze 2A), a ten 24V DC spróbuj ruszyć również z tego zasilacza do laptopa - jak chcesz się nim tylko pobawić na zasadzie pokręcenia wałem to powinien spokojnie wał się poruszyć.

    OdpowiedzUsuń
  6. Gdzie są podłączone ENABLE i HALF/FULL ?

    OdpowiedzUsuń
    Odpowiedzi
    1. Gdzie zechcesz (którykolwiek cyfrowy pin mikrokontrolera). Ich funkcje autor opisał w artykule.

      Usuń
  7. Mam pytanie. Jakie są zamienniki diód użytych w schemacie ? W ostateczności mogę zastosować diody 1n4148 ?

    OdpowiedzUsuń
    Odpowiedzi
    1. Standardowa 1N4148 ma dość mały prąd przewodzenia If rzędu 100-200mA. Są werskje z większym prądem, ale to wyjątki. Autor tego projektu zastosował diody z If=1A, i taką warto dać w szczególności, gdy nie są to malutkie silniki. Dla małych 1N4148 powinna wystarczyć.

      Zamienniki łątwo znaleźć w wyszukiwarkach dużych sklepów internetowych: SB1100 , SB140 , SB150 ... itp.

      Usuń
  8. Ten komentarz został usunięty przez autora.

    OdpowiedzUsuń
  9. jakie zasilanie samego silnika z tym projekcie?

    OdpowiedzUsuń
  10. A czy jest jakaś podoba program dla ATmega32?

    OdpowiedzUsuń
    Odpowiedzi
    1. Śmiało możesz wzorować się na tym.

      Usuń
    2. A mógłbyś podać jak powinny wyglądać funkcje "w lewe" i "w prawo" dla ATmegi przy sterowniku ULN2803? Podłączonym kolejno do pinów: PD5, PD4, PD3, PD2. Bardzo proszę o pomoc.

      Usuń
  11. Czy jeśli chcę sterować trzema silnikami krokowymi (każdy z inną częstotliwością ! ) to potrzebuje to robic w osobnych przerwaniach (potrzebuję 3 timery?)? i czy zwykłą ATmegą16 da rade to zrealizować ?

    OdpowiedzUsuń
    Odpowiedzi
    1. Nie wystarczy jeden timer o częstotliwości przerwań odpowiednio wysokiej. W co którymś przerwaniu (w zależności od wymaganej częstotliwości kroków) wywołujesz funkcję realizującą krok dla poszczególnych silników. Można też to zrobić z wieloma timerami, tyle, że ATMegi ich za wiele nie mają. Dlatego zamiast M16 lepiej i taniej użyć np. XMEGA16 A4.

      Usuń

Działy
Działy dodatkowe
Inne
O blogu




Dzisiaj
--> za darmo!!! <--
1. USBasp
2. microBOARD M8


Napisz artykuł
--> i wygraj nagrodę. <--


Co nowego na blogu?
Śledź naszego Facebook-a



Co nowego na blogu?
Śledź nas na Google+

/* 20140911 Wyłączona prawa kolumna */
  • 00

    dni

  • 00

    godzin

  • :
  • 00

    minut

  • :
  • 00

    sekund

Nie czekaj do ostatniego dnia!
Jakość opisu projektu także jest istotna (pkt 9.2 regulaminu).

Sponsorzy:

Zapamiętaj ten artykuł w moim prywatnym spisie treści.