Skocz do zawartości

[AVR] Sterownik silnika elektrycznego oparty na ISOBUS


rafisoltys

Pomocna odpowiedź

Witajcie,

Chciałbym skonsultować z wami swój projekt układu i programu mającego na celu sterowanie prędkością silnika elektrycznego w zależności od prędkości ciągnika rolniczego.

Sygnał prędkości pojazdu podawany jest na złącze ISOBUS i ma następującą charakterystykę:

Stan wysoki powyżej 6,3 V

Stan niski poniżej 1,3 V

Wypełnienie stanem wysokim 20%

Wypełnienie stanem niskim 80%

Charakterystyka sygnału = 130 Hz/m/s

Sterowanie ma odbywać się w następujący sposób:

Dla prędkości 15 km/h (4,16 m/s * 130 impulsów=541,6 Hz) silnik z przekładnią ślimakową ma pracować z pełną prędkością PWM = 100 %.

Prędkość obrotowa silnika ma być proporcjonalna do prędkości ciągnika rolniczego (Wartość PWM maleje liniowo do 0 dla prędkości 0 km/h).

Parametry silnika:

Silnik 12 V DC o mocy 220 W i maksymalnej prędkości obrotowej 3000 obr/min (Przekładnia ślimakowa i=60, Moment na wyjściu 20 Nm)

Schemat układu

Przedstawiony poniżej kod w celu wizualizacji wyników wyświetla wartość prędkości obrotowej i częstotliwość sygnału na porcie szeregowym.

W komentarzu przedstawiłem funkcję, która ma na PIN5 ustawić odpowiednią wartość PWM.

volatile int obroty = 0;
int rpm = 0;
double pwm=0;
unsigned long lastmillis = 0;
void setup(){
Serial.begin(9600); // inicjalizacja połączenia szeregowego
attachInterrupt(0, rpm_fan, RISING); // inicjalizacja przerwania  INT0 (PIN2) uruchamiajacej funkcje rpm_fan, reagujacego ba zbocze rosnące
}
void loop(){
if (millis() - lastmillis == 1000){ // obliczenia odbywają się co sekundę, 
detachInterrupt(0);//wyłącz przerwania na czas obliczeń
rpm = obroty * 60; // Przekształć częstotliwość (prędkość obrotowa na sekundę) na prędkość obrotową na minutę RPM.
Serial.print("RPM =\t"); //wyświetl "RPM"
Serial.print(rpm); // wyświetl wartość prędkości obrotowej (RPM)
Serial.print("\t Hz=\t"); //wyświetl "Hz"
Serial.println(obroty); //wyświetl zliczoną wartość impulsów (obrotów) w czasie 1 sekundy.


pwm = rpm * 0,85 * 0,1 * rpm ; // oblicz wartość pwm z funkcji liniowej (0 PWM dla 0 RPM i 255 PWM dla 541 RPM)
if(pwm>=25,5 && pwm<256); // jeśli pwm większe równe 10 % (od 25,5) i mniejsze od 256 to
{
Serial.print("PWM =\t"); // wyświetl dla testu wartość PWM
Serial.println(pwm); // digitalWrite(5,pwm); ustaw PWM o wartości pwm na PIN 5
}

obroty = 0; // wyzeruj licznik obrotów
lastmillis = millis(); // Odświerz zmienną lastmillis o nowy czas systemowy
attachInterrupt(0, rpm_fan, RISING); //uruchom przerwania
 }
}
// ta część kodu zostanie wykonana podczas przerwania (zbocze narastające) dla INT0 (PIN 2)
void rpm_fan(){
obroty++;
}

Problemy i pytania dot. UKŁADU:

Czy zastosowanie transoptora jest dobrym rozwiązaniem, do przekształcenia napięcia sygnału prędkości ?

Czy sygnał prędkości powinien być podpięty do transoptora przez rezystor ??

Czy sterowanie silnikiem DC może być realizowane za pomocą MOSFET Buzz11 ?

Czy bramka MOSFET powinna być podciągnięta rezystorem do GND ?

Czy zastosowanie tranzystora BC332 jest konieczne do sterowania MOSFETEM ?

Problemy i pytania dot. KODU:

Do testowania programu wykorzystuję wentylator PC i jego wyjście sygnałowe.

Program wyświetla ciągle wartość zmiennej pwm=0 niezależnie od prędkości obrotowej (warunek pętli większe od 25,5 i mniejsze 256 spełniony). Jaka może być tego przyczyna ?

Dokładność pomiaru jest dosyć słaba. Pomimo tego, że wentylator zasilany jest zewnętrznego źródła (brak sterowania) odczyt prędkości ma spory rozrzut. Jak można zwiększyć dokładność ?

Z góry dziękuję za pomoc.

Link do komentarza
Share on other sites

Tak na pierwszy rzut oka:

1) Nie wyłączaj przerwań na czas obliczeń (po co?). Zainteresuj się makrem ATOMIC_BLOCK, coś w stylu:

#include <avr/utils.h>
...

ATOMIC_BLOCK(ATOMIC_FORCEON) {
   obroty_local = obroty;
   obroty = 0;
}
rpm = obroty_local * 60;

Do tego do pomiaru czasu użyj lepiej timera, w ostateczności micros() - millis() może być tu niedokładne.

Tutaj masz linka. Przy timerze nie masz problemu z blokowaniem przerwań licznika obrotów...

Link do komentarza
Share on other sites

Odniosę się tylko do sprzętu:

1. Zastosowanie transoptora jest OK - zadziała, chociaż tu jest zupełnie niepotrzebny. Skoro i tak nie masz optoizolacji bo łączysz masę wejściową z cyfrową procesora, to to samo uzyskasz przez użycie dzielnika z dwóch oporników.

2. Gwarantowane napięcie minimalne na wejściu prędkości jest trochę za duże do takiego sterowania diodką transoptora. Istnieje niebezpieczeństwo, że nawet przy 1.3V może trochę świecić. Dlatego oprócz (obowiązkowego) R1 włącz tam szeregowo jeszcze ze dwie zwykłe diody krzemowe. Z kolei maksymalne napięcie 6.3V powinno dawać przepływ dosłownie kilku mA, więc R1 powinien być wtedy w okolicach (6.3V-1.1V-(2*0.7V))/5mA= 750Ω. Coś w granicach 620-750Ω będzie w sam raz.

3, 4, 5. BUZ11 to MOSFET N-kanałowy więc musisz go użyć zupełnie inaczej. To stary tranzystor więc wymaga dużego dodatniego napięcia na bramce. Musisz zrobić driver z tranzystora npn taki, aby dawał 0V/12V na bramkę (czyli baza tak jak teraz a w kolektorze opornik 1k do +12V). Wtedy źródło BUZa stawiasz na masie, bramkę dajesz do kolektora npn a w dren wstawiasz silnik, którego drugi koniec dajesz do plusa. No niestety w tym układzie silnik nie będzie podłączony żadnym końcem do masy - jeśli to nie jest dla Ciebie istotna wada, to tak zrób. Układ który pokazałeś nie zadziała w ogóle. Narysuj to, wtedy pomyślimy co dalej.

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

ethanak

Podchodziłem do timerów już kilkakrotnie. Opierałem się na przykładzie z http://mikrokontrolery.blogspot.com/2011/04/obrotomierz-diy.html jednak nie udało mi się go przekształcić zgodnie ze swoimi potrzebami.

Przeczytałem kilkukrotnie notę katalagową uC i wydaje mi się, że w dużym stopniu rozumiem obsługę przerwań jednak nie udało mi się jej użyć. Zawsze pojawia się jakieś pytanie, na które nie znam odpowiedzi. Najgorsze dla mnie jest to, że czuję, że to jest bardzo prosty program i jeszcze prostszy układ a sprawia mi tyle problemów.

marek1707,

Wprowadziłem zmiany w schemacie.

Za twoją radą zastosowałem dzielnik napięcia. Wydaje się być rozwiązaniem o wiele prostszym.

Zmieniłem również schemat podłączenia BUZZ11 oraz dodałem filtrowanie zasilania uC.

Masa pozostaje wspólna.

Link do komentarza
Share on other sites

Zawsze pojawia się jakieś pytanie, na które nie znam odpowiedzi.

To zapytaj - nie kosztuje.

Przy okazji - w linku który podałem masz przykład zastosowania takiego prostego timera - nic tylko popatrzeć i napisać.

Procedura przerwania zegarowego to mniej więcej coś takiego:

void timerProc(void)
{
   rpm = obroty * 60;
   obroty = 0;
}

Pamiętaj, że rpm musi być w tej sytuacji zdeklarowany jako volatile, a odczyt tej zmiennej umieszczasz w bloku ATOMIC.

Tyle - prościej się juz chyba nie da...

Link do komentarza
Share on other sites

Pokaż aktualny schemat z naniesionymi wartościami elementów, chciałbym mieć pewność że się zrozumieliśmy. Poza tym wciąż mogą istnieć problemy drugiej ważności, być może trzeba się nad nimi pochylić.

Pierwszy który przychodzi mi do głowy na starcie to brak kondensatorów na wyjściu stabilizatora i tym samym zasilaniu procesora - to nie ma prawa działać. Po drugie to zabezpieczenie wejścia przed zasilaniem z instalacji samochodowej(?).

Link do komentarza
Share on other sites

Nie, nie jest OK. To co narysowałeś jest na razie naiwnym wyobrażeniem gimnazjalisty o elektronice.

1. Ja bym wykorzystał już zrobiony dzielnik R6/R7 jako filtr. Nie wiesz pewnie jak wyglądają impulsy przychodzące z zewnątrz, ale w instalacji samochodowej lepiej uważać i dodać kondensator niż potem zastanawiać się dlaczego wyniki pomiarów są głupie. Daj z 10nF równolegle do R7 do masy. Potem ew. to zwiększysz, ale będziesz miał już miejsce na płytce.

2. Jeśli Q2 ma w kolektorze 1k to dla 12V potrzebujesz 12mA żeby wchodził w nasycenie. Teraz dałeś jakieś strasznie małe oporniki w jego bazie i pompujesz tam 10mA a spokojnie wystarczy 1. Nie musisz obciążać portu biednego procesora takim prądem. Daj R3 w granicach 1.0-2.2k a R5 podłącz zupełnie inaczej. Pomyśl, po włączeniu zasilania, zanim standardowy bootloader Arduino przekaże sterowanie do Twojego kodu a ten zaprogramuje piny portów, miną ze 2 sekundy. W tym czasie tranzystor będzie za sprawą (obecnego) R5 wyłączony więc na jego kolektorze dostaniesz 12V i silnik ruszy z kopyta. To chyba źle, prawda? Musisz tak to zbudować, by Q1 był samodzielnie załączany opornikami a dopiero procesor go wyłączał (tym samym odpalając silnik) przez podanie stanu niskiego lub PWMa na bazę. Daj R5=5.1k od portu procesora (nie od bazy Q1) wprost do Vcc.

3. Coś mi te numery nóżek MOSFETa nie pasują, bo zwykle bramka jest z boku a dren w środku, co by sugerowało inne numerki. Sprawdź to dobrze podczas robienia PCB. Kto robił ten symbol, bo dziwnie to wygląda. Dioda podłożowa jest niby dobrze, ale ta nadmiarowa strzałka(?) z boku kanału jest dół(!). To bez sensu, ktoś chyba nie rozumiał co rysuje.

4. Nie podłączaj AREF wprost do VCC. Masz taką możliwość programowo - jako jedną z kilku opcji i w razie czego możesz to zrobić (lub nie) wprost z kodu. Dzięki temu zostawiasz sobie możliwość wyboru innego napięcia referencyjnego dla ADC. Oczywiście 100nF tam zostaw.

5. Na wejściu stabilizatora, od strony +12V daj: diodę szeregową i opornik z 10Ω a za tym daj do masy ze 100uF, diodę Zenera 18-24V i te istniejące 100nF. To wytnie sporo szpilek i śmieci przychodzących z instalacji oraz zabezpieczy przed ew. odwrotnym podłączeniem zasilania. Procesory nie lubią takich rzeczy na swoim Vcc a szybkie zakłócenia przechodzą przez 7805 jak nóż przez masło.

6. Pobierz wyjście PWM ze sprzętowego wyjścia timera - od tego je masz i za nie zapłaciłeś, korzystaj z nich. To nie może być Timer 0 (jak teraz) bo ten jest zawłaszczony przez system Arduino m.in. do liczenia czasu. Skorzystaj z Timera 1 lub 2.

7. Moim zdaniem malutka dioda 1n4148 nie wystarczy do gaszenia silnika 200W. Daj tam szybką diodę Schottky na 3A, np. SK34. Oczywiście sam silnik powinien dostać kondensatory przeciwzakłóceniowe, dławiki itd, ale to już montowane bezpośrednio na nim a nie tu na schemacie. Mam nadzieję, ze to wiesz.

Link do komentarza
Share on other sites

1. DONE.

2. Mam wątpliwość czy dobrze zrozumiałem sugerowany przez Ciebie sposób połączenia.

3. Schemat BUZ11 pochodzi z biblioteki EasyEDA. MOSFET podłączę zgodnie z notą katalogową.

4. DONE.

5. DONE.

6. Przekładnia ślimakowa ma sprawność około 65 %. Myślę, że bardzo szybko go wyhamuje, jednak pomyślę nad większą diodą.

Link do komentarza
Share on other sites

Jest coraz lepiej, ale:

1. Dioda na wejściu jest odwrotnie (no weź, proszę Cię..) EDIT: I nie siej wszędzie tych maluchów, daj 1N4004 czy coś podobnego 1A i z głowy. Przecież to tanie jak piach.

2. Dioda Zenera anodą na masie, katodą do wejścia stabilizatora plusa - ma obcinać szpilki powyżej 24V. EDIT: 1N5351 to dioda 14V a tyle to możesz mieć w instalacji normalnie podczas ładowania. Zjarasz wtedy i opornik szeregowy i samą diodę. Miało być 18-24V, nie zmyślam tych liczb z sufitu, musisz mieć spory zapas by w normalnych sytuacjach nigdy nie przewodziła.

3. R5 do +5V a nie do +12V - procesor raczej tego nie przeżyje.

4. D1 Nie służy do hamowania silnika w bezpośrednim sensie tylko do zamykania obwodu gdy tranzystor jest wyłączony a silnik wciąż się kręci. Taka sytuacja zachodzi w każdym okresie PWM. Rzeczywiście, silnik obciążony taką przekładnią nie odda za dużo ze swojego back-EMF, ale na pewno trzeba wstawić coś większego niż szklany paciorek 1N4148. Jakaś szybka diodka chociaż 1-3-5A byłaby na miejscu, najlepiej zamontowana na silniku bo wtedy zamyka oczko na krótko bez kabli.

5. Brakuje mi jeszcze jakiegoś 10-22uF na wyjściu 7805. Same ceramiczne 100nF to trochę mało na dłuższe (ms) zaniki.

6. Czy to będzie osobna płytka czy jakieś Arduino przerobione? Bo jeśli samodzielny projekt, to wypadałoby zrobić link do debugowania, choćby wyjście na terminal szeregowy z TXD/RXD. Skąd będziesz wiedział, że program w ogóle coś odbiera, że wyniki pomiarów są poprawne i jaki PWM wystawił?

7. No i dałbym ze dwie-tzry diodki LED, zawsze to lepiej wiedzieć bez przyrządów w polu, że:

a. Jest zasilanie +5V

b. Program ruszył i zaprogramował porty

c. Odbiera impulsy z wejścia

Link do komentarza
Share on other sites

Pewnych rzeczy się wstydzę więc nawet nie skomentuję 😳

1. Dam większą mam na stanie 3A

2. Dobrałem teraz taką z 22V

3. Done

4. Tutaj również dioda 3A

5. Done

6. Do testów będzie Arduino, potem uC przełożę w podstawkę na płytce.

7. Dioda sygnalizująca zasilanie 12V, Dioda z kondensatorem 1u sygnalizujaca odbieranie sygnału, dioda na Pin 17 program poda również PWM na nią.

Link do komentarza
Share on other sites

Dodając diody LED myślę, że jedna "sprzętowo" pokazująca zasilanie (i to raczej 5V bo to daje więcej informacji - wiadomo że procesor ma VCC) wystarczy. Pozostałe napędzaj z procesora. Daj mu dwie lub trzy, niech to program ma szansę zapalać je w różnych sytuacjach. Sam zobaczysz, jak bardzo to się przydaje podczas pisania kodu. Diodę na wejściu wywal. Nie dość, że ten nowy kondensator będzie za bardzo filtrował sygnał to jeszcze dioda wymaga sporego prądu a ten będziesz dostarczał przez opornik wejściowy. Skoro dzielnik był jakoś policzony dla przypadku tylko dwóch oporników, to teraz obciążenie go LEDem spowoduje znaczny spadek napięcia. Wstawiając takie modyfikacje zawsze sprawdzaj , czy nie popsułeś już raz zrobionej i przemyślanej funkcji.

Jeśli chcesz mrugać diodką "sprzętowo" z sygnału po dzielniku to daj jej tranzystor, który praktycznie wcale nie obciąży dzielnika bo w bazie wystarczy mu np. 51k albo będzie to mały MOSFET np. typu FDV301 czy coś podobnego. Albo napędzaj diodę z wejścia przez jej własny opornik, ale wtedy musisz wiedzieć jak silne jest źródło. Czym innym jest zrobienie na wejściu dzielnika widzianego z zewnątrz jak rezystancja kilka kΩ a czym innym bezpośrednie obciążenie wejścia diodą LED. Poza tym dioda taka będzie pokazywać coś, co wcale nie jest stanem logicznym widzianym przez procesor i program.

Jak już wspomniałem - pomijając diodę VCC_5V - oparł bym się na diodkach czysto "procesorowych". Przecież program może sobie mrugnąć którąś za każdym razem gdy wykryje zbocze. A jeśli ta funkcja Ci się znudzi, możesz np. świecić gdy impulsy przychodzą a gasnąć po 2 sekundach przerwy. Możliwości takich sygnalizacji są nieograniczone. W tak prostym programie 2-3 diody wystarczą do rozumienia co w danej chwili procesor robi. Acha, i zakładaj, że diodom przewlekanym wystarcza raczej 5-10mA, przecież masz tylko coś sygnalizować a nie oświetlać tym pokój. Do takiego prądu licz ich oporniki. W tym kontekście 100Ω to jednak lekkie przegięcie. A małe diody SMD zadowalają się obecnie prądami <1mA...

W każdym razie układ powoli zaczyna dojrzewać do działania 🙂

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.