Skocz do zawartości

Arduino i sterownik silnika krokowego dm542


240volt

Pomocna odpowiedź

Witam,

Mam następujący problem. Za pomocą Arduino UNO chcę sterować pracą dwóch silników krokowych. Silniki podłączone przez sterownik dm542. Dodatkowo arduino ma osługiwać również przyciski i wyświetlacz graficzny. Chcę aby silniki krokowe pracowały niezależnie od obsługi programu głównego tak więc generowanie sygnału przeniosłem do obsługi przerwania od timera za pomocą biblioteki TimerOne.

#include "TimerOne.h"

void setup() 
{
  pinMode(2,OUTPUT);			//Pin podający impuls kroku na sterownik
  pinMode(3,OUTPUT); 			//Pin podający sygnał kierunku obrotów
  Timer1.initialize(900);       //Okres zmian stanu na pinie 2 (co 900 mikrosekund)
  Timer1.attachInterrupt(Przerwanie);   
}

void Przerwanie()
{
  digitalWrite(2, digitalRead(2) ^ 1);  // zmiana stanu pinu na przeciwny
}

void loop()
{
digitalWrite(3, digitalRead(3) ^ 1); 	//zmiana kirunku obrotów na przeciwny
delay(1000);			//delay udowadniający że silnik pracuje "niezależnie" od pętli głównej programu
}

Program działa, jednak mam co do niego kilka zastrzeżeń. Po pierwsze można sterować tylko jednym sterownikiem, po drugie nie da się w programie sterować prędkością silnika ponieważ, okres przerwań ustawia się w funkcji setup.

Myślałem żeby zastosować bibliotekę Timers, jednak tam nie można ustawiać czasu w mikrosekundach,a przy 400 krokach na obrót i 60-80 obrotach na minutę impulsy na sterowniku muszą się pojawiać się co 1-3ms.

Czy ktoś może zna lepszą bibliotekę dla moich potrzeb? Ewentualnie jak w bibliotece timers ustawić interwał przerwań w us?

Z góry dziękuję za pomoc.

Edytowano przez 240volt
  • Lubię! 1
Link do komentarza
Share on other sites

Cześć,

patrząc na dokumentację użytej przez Ciebie biblioteki "Timerone" :

https://playground.arduino.cc/Code/Timer1/

wydaje mi się, że można zmienić okres "podczas" działania programu metodą: setPeriod(period)  - co prawda głowy za to nie dam, bo nie robiłem prób . Po drugie co stoi na przeszkodzie aby w obsłudze przerwania sterować drugim silnikiem  - trzeba tylko trochę rozbudować kod (dodać jakieś ify, inkrementację liczników itp).

Pozdrawiam

  • Lubię! 1
  • Pomogłeś! 1
Link do komentarza
Share on other sites

(edytowany)

setPeriod() niestety nie działa (program nie chce się skompilować "'setPeriod' was not declared in this scope") ale okazało się że Timer1.initialize(); działa, tak więc problem ze zmianą prędkości obrotowej w trakcie pracy udało się opanować.

Dzięki za podsunięcie pomysłu z rozbudowaniem obsługi przerwania jest to jakieś wyjście ale wydaje mi się że musi być prostsze rozwiązanie, w końcu na arduino można zrobić drukarkę 3d a tam trzeba ogarniać kilka silników na raz. Tak więc czekam na pomysły.

Tymczasem mam zamiar przetestować rozbudowanie obsługi przerwania. Moje pytanie jest takie: czy jeśli przerwanie będę wywoływał co 100us, co powinno mi dać wystarczającą rozdzielczość sterowania prędkością obrotową, to tak częste przerwania nie będą wpływały na np. komunikację z wyświetlaczem graficznym po SPI?

 

Edytowano przez 240volt
  • Lubię! 1
Link do komentarza
Share on other sites

2 godziny temu, 240volt napisał:

Tymczasem mam zamiar przetestować rozbudowanie obsługi przerwania. Moje pytanie jest takie: czy jeśli przerwanie będę wywoływał co 100us, co powinno mi dać wystarczającą rozdzielczość sterowania prędkością obrotową, to tak częste przerwania nie będą wpływały na np. komunikację z wyświetlaczem graficznym po SPI?

Cześć,

musisz zrobić próby praktyczne, ale jeśli funkcja obsługi przerwania nie będzie przesadnie długa to powinno być OK.

Pozdrawiam

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

1 godzinę temu, 240volt napisał:

w końcu na arduino można zrobić drukarkę 3d a tam trzeba ogarniać kilka silników na raz.

Tak, tylko przy drukarce nie jest taka ważna rzeczywista prędkość silników, ale to, że w jednostce czasu silnik X ma wykonać dokładnie N kroków, a silnik Y dokładnie M, przy czym owa "jednostka czasu" jest dość płynnym pojęciem (soft drukarki gwarantuje, że po wydaniu np. polecenia "G0 X10 Y5" głowica drukarki przesunie się do położenia 10/5, ale nie gwarantuje że dokładnie z taką prędkością jak sobie wymarzyłeś, a w pewnych przypadkach nawet nie pojedzie po prostej).

  • Lubię! 1
Link do komentarza
Share on other sites

A więc przeprowadziłem testy z rozbudowaną obsługą przerwania. Jak się okazało wcale taka rozbudowana nie jest.

Żeby przyśpieszyć działanie programu w obsłudze przerwania zamieniłem digitalWrite(pinKroku, digitalRead(pinKroku) ^ 1); na PORTD ^= (1 << PD7);

Testy przeprowadzam na razie na jednym sterowniku silnika krokowego, interwał przerwań to 100us, w pętli loop wysyłam dane po UART do monitora - wszystko działało... do czasu.

Schody zaczęły się gdy postanowiłem przetestować funkcję powolnego rozruchu silnika. W tym celu w loopie co jeden obieg zmniejszam czas pomiędzy kolejnymi impulsami do sterownika, tak jak to widać w poniższym programie. Niestety efekt jest taki że zmienna "predkosc_karetka" dekrementuje się, silnik zwiękasza obroty, a gdy zmienna osiągnie wartość 12 dochodzi jakby do zawieszenia się timera. Pętla główna programu działa wysyła kolejne wiadomości przez uart natomiast na pinie na którym powinien generować się sygnał dla dm542 pojawia się na kilka - kilkanaście sekund stan niski lub wysoki, z tego powodu silnik nie pracuje (bo nie ma odpowiedniego sygnału na wejściu sterownika).

A TERAZ MAGIA...

Dzieje się tak tylko wtedy jeżeli wartość delaya w loopie jest inna niż 200. Czyli delay == 199; 201; 300;400;500;600;700;800;900;1000 - timer się zawiesza. Delay == 200 wszystko pracuje prawidłowo.

Czy ktoś wie co ma piernik do wiatraka (a w tym przypadku delay w loopie do przerwań od timera?)

Żeby było jeszcze dziwniej, jeżeli nie dekrementuje zmiennej w loopie tylko od razu ustawiam ją na wartość 12 to wszystko działa.

 

#include "TimerOne.h"

int predkosc_karetka = 20;  //(*100us)    <<<====================
int k = 0;

#define pinKroku 7
#define pinKierunku 3

void setup()
{
  pinMode(7, OUTPUT);     //Pin podający impuls kroku na sterownik
  pinMode(3, OUTPUT);     //Pin podający sygnał kierunku obrotów
  Timer1.initialize(100);  //Okres zmian stanu na pinie 2 
  Timer1.attachInterrupt(Przerwanie);
  Serial.begin(9600);
}

void Przerwanie()
{
  k++;
  if (k == predkosc_karetka)
  {
    PORTD ^= (1 << PD7);
    k = 0;
  }
}

void loop()
{
  predkosc_karetka--;
  if (predkosc_karetka <= 3) predkosc_karetka = 3;
  Serial.println("Aktualna predkosc to:");
  Serial.println(predkosc_karetka);
  delay(200);
}

 

Link do komentarza
Share on other sites

Dziękuję za odpowiedzi jednak trafiłem na bardzo ciekawą bibliotekę "AccelStepper".Silnik krokowy pracuje idealnie. Zwalnianie i przyśpieszanie aż miłe dla uszu. Natomiast ma jedną wadę, mianowicie w pętli loop należy jak najczęściej wykonywać stepper1.run(); No i znowu pojawia się problem ponieważ jak dodam w loopie wysyłanie danych po uart to silnik nie pracuje prawidłowo.

Przeniosłem polecenie stepper1.run(); do obsługi przerwania od timera. Obsługa przerwania musi być wywoływana co 50us żeby silnik pracował bezproblemowo. Komunikacja przez uart działa, tak więc na razie nie widać większych problemów. Zobaczymy jak sobie poradzi Arduino z podłączonym sterownikiem do drugiego silnika.

Załączam aktualny kod. Wrócę z informacjami jak bardziej rozbuduję układ.

#include "TimerOne.h"
#include <AccelStepper.h>

#define dirPin 3
#define stepPin 7
#define motorInterfaceType 1

AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

void Przerwanie()
{
  stepper.run();
}

void setup()
{
  stepper.setMaxSpeed(1000);
  stepper.setAcceleration(500);
  Timer1.initialize(50);  //Okres wywoływania obsługi przerwania
  Timer1.attachInterrupt(Przerwanie);
  Serial.begin(9600);
}

void loop()
{
  stepper.moveTo(80000);
  Serial.println("Jakis tekst do wyslania po UART");
  delay(1000);
}

 

  • Lubię! 1
Link do komentarza
Share on other sites

Powiem tak: ostatnio zacząłem projektować coś podobnego (na szczęście do realizacji nie doszło, bo okazało się że gość chce mieć urządzenie ale nie ma pieniędzy). Planowałem użycie ESP32 i biblioteki ESP-FlexyStepper. Niestety, przerwałem pracę na bardzo wczesnym etapie, tak że nie mogę nic powiedzieć na temat tej biblioteki.

Gdybym miał coś takiego jak Ty robić na Arduino odżałowałbym te paręnaście złotych i użył drugiego Arduino jako sterownika silników. Odbierałby sobie dane po serialu i nie miał nic więcej do roboty, tylko merdać silnikami. Pierwszy (główny) Arduino robiłby całą resztę - wyświetlacz, klawiatura, jakiś program ustalający prędkości silników, jeszcze jakieś wodotryski) i wywalał na seriala tylko prędkości. Pewnie są jakieś inne/lepsze rozwiązania, ale to wydaje mi się najprostsze i najszybsze w realizacji.

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.