czwartek, 17 sierpnia 2017

L298N - moduł sterownika silników DC i krokowych

Moduł sterownika L298N umożliwia niezależne sterowanie dwoma silnikami prądu stałego lub jednym silnikiem krokowym. Układ scalony L298N jest podwójnym mostkiem H. Mostek stąd, że łączy bieguny silnika z zasilaniem (naprzemiennie - co wpływa na kierunek obrotów), a "H" bo typowy układ elektryczny obrazujący działanie mostka przyjmuje kształt tej litery.


Moduł sterownika

O teorii i realizacji mostka można poczytać w przystępnym poście na forum forbot.pl. Oczywiście teoria nie jest niezbędna do tego, aby w końcu silniki podłączone do modułu zaczęły się kręcić. Dodam, że jest jeszcze parę innych mostków w elektronice, a najsłynniejszym i najczęściej wałkowanym jest mostek prostowniczy (Graetza) stosowany w zasilaczach sieciowych. Inne można znaleźć na stronach wikipedii.

Cechy układu L298N
  • sterowanie TTL (0-5V)
  • zasilanie do 46V
  • prąd wyjściowy max 2A na kanał
  • prąd zasilania 36mA
  • sterowanie:
    • kierunek obrotu (przód/tył) z regulacją prędkości PWM
    • szybkie zatrzymanie silnika
    • swobodne zatrzymanie silnika
  • zabezpieczenie przed przegrzaniem

Cechy modułu
  • wbudowany stabilizator napięcia dla części logicznej układu L298N, dzięki czemu można zasilić moduł jednym napięciem
  • złącza ARK do podłączenia zasilania układu oraz silników


Piny modułu

Pin(y) Opis
+12V Napięcie zasilania silników. W praktyce jak przypuszczam, będzie to mogło być zasilanie z przedziału od 7 do 35V, czyli takie przy którym będzie bezproblemowo pracował wbudowany stabilizator napięcia 5V. Oczywiście napięcie te nie może przekraczać dopuszczalnego napięcia pracy silników.
+5V Wejście (brak zworki CON5) lub wyjście (wstawiona zworka CON5) napięcia 5V. Opis niżej w tabeli poświęconej zworkom w module
GND Masa układu
OUT1, OUT2 Wyjścia kanału silnika A
OUT3, OUT4 Wyjścia kanału silnika B
ENA Sygnał PWM do sterownia prędkością obrotową silnika A
ENB Sygnał PWM do sterownia prędkością obrotową silnika B
IN1, IN2 Sterowanie kierunkiem silnika kanału A
IN3, IN4 Sterowanie kierunkiem silnika kanału B

Zworki
Zworka Opis
ENA Ustawia napięcie 5V na wejściu ENA i silnik kanału A pracuje z maksymalną prędkością
ENB Jak dla ENA, dotyczy kanału B
CON5 Brak zworki oznacza konieczność doprowadzenia napięcia zasilania 5V dla części logicznej US L298N. Obecność zworki z kolei powoduje, że wspomniana część logiczna jest zasilana z dodatkowego stabilizatora napięcia na 5V zasilanego napięciem +12V, przeznaczonym do zasilania silników. W tym wypadku na pin-ie +5V pojawi się też napięcie 5V pochodzące ze stablizatora. Można je wykorzystać np. do zasilania arduino


Sterowanie modułem (H - stan wysoki, L - stan niski)
IN1/IN3 IN2/IN4 ENA/ENB Działanie silnika
H L PWM Maksymalna prędkość określona przez sygnał PWM na wejściu ENA/ENB zgodnie ze wskazówkami zegara
L H PWM Maksymalna prędkość określona przez sygnał PWM na wejściu ENA/ENB przeciwnie do ruchu wskazówek zegara
L L H Szybkie hamowanie silników
H H H Szybkie hamowanie silników
H H L Swobodne hamowanie


Uruchomienie

Silniki DC
Do samego sprawdzenia, czy i jak moduł "kręci" silnikami wystarczy odpowiednie wysterowanie pinów IN1...4 i zasilenie układu napięciem co najmniej 7V (do pinu +12V). Na sztywno podpiąłem 5V (można wziąć z pin +5V) i masę (0V) do IN1..4 zgodnie z tabelą powyżej. Zasilanie układu pochodziło z zewnętrznego zasilacza ustawionego na 7,5V. Tak wstępnie uruchomiłem 4 silniki zamontowane na podwoziu samochodu, poprawiając przy tym połączenia kabli silników (podłączenie do OUT1...4), tak aby kręciły się w tym samym kierunku :) W przyszłości, mam nadzieję, że powstanie z tego jakiś arduinowy pojazd.

Uruchomienie modułu

Sterowanie w arduino
Jak zwykle mnóstwo kodu można znaleźć w sieci, w tym wypadku oparłem się na kodzie z repozytorium https://github.com/jiehou/ArduinoRobotCar. Poza sterowaniem modułem L298N, zawiera jeszcze inny kod, który może przydać mi się w przyszłości do realizacji samochodu "robota". Pozmieniałem nazwy funkcji dodając słowo moto, aby było jednoznacznie wiadomo z jakim modułem jest powiązana dana funkcja. Dodatkowo dorzuciłem funkcję motorFreeBrake() pozwalającą na swobodne hamowanie silników. Szczerze mówiąc, nie zauważyłem żadnej różnicy w jej działaniu porównując do funkcji motorFastBrake(), która szybko wyhamowywuje silniki. Może będzie to lepiej widać przy zamocowanych kołach i dodanej masie pojazdu. Więcej opcji sterowania, w tym pojedynczymi kanałami, można znaleźć w artykule [Arduino] L298 Dual H-Bridge Motor Driver.

Jeszcze jedną zmianą w oryginalnym kodzie, a związaną ze sterowaniem PWM, była zmiana portów 5 i 6 (pracujących domyślnie na częstotliwości 1kHz) na 9 i 10 (pracujących domyślnie z częstotliwością 490Hz). Efekt tej zmiany był taki, minimalna wartość PWM przy której startowały silniki zmalała ze 100 do 70 (sprawdzałem pełne dziesiątki wartości). Poniżej słyszalny był jedynie pisk silników.  Temat częstotliwości sygnału PWM przy sterowaniu silników został poruszony w przytoczonym na wstępie poście z forbot.pl. Autor pisze tam, że częstotliwość ta powinna być rzędu 100Hz, a więc jest 5 razy mniejsza, niż tu użyta. Opis jak jeszcze zmniejszyć częstotliwość sygnału PWM, znalazłem na stronach playground.arduino.cc. Temat sprowadza się do odpowiedniej konfiguracji rejestrów liczników i jest to już raczej operacja niskopoziomowa jak na kod pisany pod arduino ;)

Jakiś czas później... poprawiłem połączenia kabli (dałem kolor adekwatny do bieguna, które przyjąłem umownie, bo moje silniki nie miały naniesionych biegunów). Po podłączeniu okazało się, że silniki ruszają przy sygnale PWM 200. Zmniejszyłem wobec tego częstotliwość na pinach do ok 120Hz i obecnie silniki startują przy sygnale 150. W tym celu dodałem linię w setupie konfigurującą licznik który odpowiada za częstotliwość sygnału na pinach 9 i 10:
TCCR1B = TCCR1B & 0b11111000 | 0x04;

/**
* Moduł sterownika silnika L298N
*/
const int ENA = 9;  //Enable A
const int ENB = 10; //Enable B
//IN1: H (5V);  IN2: L (GND) -> Motor A Direction 1
//IN1: L (GND); IN2: H (5V)  -> Motor A Direction 2
const int IN1 = 2;
const int IN2 = 3;
//IN3: H (5V);  IN4: L (GND -> Motor B Direction 1
//IN3: L (GND); IN4: H (5V) -> Motor B Direction 2
const int IN3 = 4;
const int IN4 = 7;

const int timeDelay = 500;

boolean run;

void setup() {
    TCCR1B = TCCR1B & 0b11111000 | 0x04;
    pinMode(ENA, OUTPUT);
    pinMode(ENB, OUTPUT);
    pinMode(IN1, OUTPUT);
    pinMode(IN2, OUTPUT);
    pinMode(IN3, OUTPUT);
    pinMode(IN4, OUTPUT);
    digitalWrite(ENA, LOW);
    digitalWrite(ENB, LOW);

    run = true;
}

void loop() {
    if (run) {
        delay(2000);
        motorForward(255);
        delay(2000);
        motorFastBrake();
        delay(2000);
        motorBackward(255);
        delay(2000);
        motorFreeBrake();
        delay(5000);
        motorLeft(128);
        delay(2000);
        motorRight(128);
        delay(2000);
        motorFastBrake();
        
        run = false;
    }
}

/**
* Forward
*/
void motorForward(int speed)
{
    analogWrite(ENA, speed);
    analogWrite(ENB, speed);
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, HIGH);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, HIGH);
}

/**
* Backward
*/
void motorBackward(int speed)
{
    analogWrite(ENA, speed);
    analogWrite(ENB, speed);
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, HIGH);
    digitalWrite(IN4, LOW);
}

/**
* Left
*/
void motorLeft(int speed)
{
    analogWrite(ENA, speed);
    analogWrite(ENB, speed);
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, HIGH);
    digitalWrite(IN3, HIGH);
    digitalWrite(IN4, LOW);
}

/**
* Right
*/
void motorRight(int speed)
{
    analogWrite(ENA, speed);
    analogWrite(ENB, speed);
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, HIGH);
}

/**
* Fast break
*/
void motorFastBrake()
{
    analogWrite(ENA, 255);
    analogWrite(ENB, 255);
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, HIGH);
    digitalWrite(IN3, HIGH);
    digitalWrite(IN4, HIGH);
    delay(timeDelay);
}

/**
* Free break
*/
void motorFreeBrake()
{
    analogWrite(ENA, 0);
    analogWrite(ENB, 0);
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, HIGH);
    digitalWrite(IN3, HIGH);
    digitalWrite(IN4, HIGH);
    delay(timeDelay);
}

Silniki krokowe

Tu wziąłem jeden z przykładów dotyczących silników krokowych, dostępny w przykładach w Arduino IDE o nazwie stepper_ oneRevolution. Użyłem tu silnika 17HS4401, który ma cztery piny sterujące (w sumie 6, ale 2 nie używane).

L298N z silnikiem krokowym

/*
 Stepper Motor Control - one revolution

 This program drives a unipolar or bipolar stepper motor.
 The motor is attached to digital pins 8 - 11 of the Arduino.

 The motor should revolve one revolution in one direction, then
 one revolution in the other direction.


 Created 11 Mar. 2007
 Modified 30 Nov. 2009
 by Tom Igoe

 */

#include <Stepper.h>

const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution
// for your motor

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

void setup() {
  // set the speed at 60 rpm:
  myStepper.setSpeed(60);
  // initialize the serial port:
  Serial.begin(9600);
}

void loop() {
  // step one revolution  in one direction:
  Serial.println("clockwise");
  myStepper.step(stepsPerRevolution);
  delay(500);

  // step one revolution in the other direction:
  Serial.println("counterclockwise");
  myStepper.step(-stepsPerRevolution);
  delay(500);
}

Podpięcie odułu L298N do silnika krokowego:
OUT1 -> A- (zielony kabel / Pin4)
OUT2 -> A+ (czerwony kabel / Pin6)
OUT3 -> B- (niebieski kabel / Pin1)
OUT4 -> B+ (żółty kabel / Pin3)

Zasilanie modułu 12V, zwarta zworka CON5.

Źródła
1)  [Teoria] Mostek H (H-bridge) - kompendium dla robotyka
2) Specyfikacja L298N
3) PWM frequency for linear motion control
4) Pwm Frequency in Arduino
5) ArduinoRobotCar
6) All About Stepper Motors
7) Stepper Library
8) Control Stepper Motor with L298N Motor Driver & Arduino

Brak komentarzy:

Prześlij komentarz