Skocz do zawartości

Serwomechanizm- problem z utrzymaniem pozycji po ponownym włączeniu zasilania


alshrom

Pomocna odpowiedź

Cześć wszystkim!

Zostałem postawiony przed koniecznością stworzenia pewnego mechanizmu. Jedna z jego części ma działać w następujący sposób:

Przy załączonym przycisku klapka ma otwierać się w stronę krańcówki K1. W momencie osiągnięcia K1 krańcówka wysyła sygnał do arduino i napęd ma się wyłączyć. Przy wyłączeniu przycisku klapka powinna wrócić w położenie K2. Klapka ma pokonać dystans 80mm w czasie ~2sek. Pierwotna koncepcja zakładała wykorzystanie zwykłego silniczka ze śrubą pociągową, lecz niestety gabaryty nie pozwalają na zastosowanie takiego rozwiązania. Zdecydowałem się więc na użycie serwomechanizmu (jest mały, zapewnia duży moment, łatwo sterować prędkością otwierania klapki). Ogólnie po napisaniu programu wszystko działało zgodnie z założoną logiką, lecz problem pojawił się po ponownym uruchomieniu arduino. Po osiągnięciu pozycji K1 i przy załączonym przycisku odłączyłem zasilanie. Po ponownym uruchomieniu, serwomechanizm ustawił się szybko na pozycję 90 stopni, choć przycisk cały czas był wciśnięty serwo nie dążył do pozycji K1. Dopiero po wyciśnięciu przycisku serwo wykonało ruch (niestety szybki, a nie powolny jak zaprogramowałem) w pozycję K2. Do stworzenia prototypu użyłem elementów z zestawu startowego arduino.

Niestety, ale w swoim projekcie nie mogę sobie pozwolić na to by po ponownym podłączeniu zasilania serwo wykonywało jakieś szybkie ruchy na pozycje 0. Czy jest jakiś sposób, który może rozwiązać mój problem? Dodam, że moja wiedza z programowania jest podstawowa, więc proszę o prosty język i wyrozumiałość.

W kodzie mam sterowanie na dwa przełączniki, ale nie ma to większego znaczenia.

#include<Servo.h>
int pos =0;

Servo servo;


void setup() {
pinMode(10, INPUT); //przelacznik 1
pinMode(9, INPUT); //przelacznik 2
pinMode(8, INPUT); //krancowka na otwarciu
pinMode(7, INPUT); //krancowka na zamknieciu

servo.attach(3);
}

void loop() 
{
     

   
      //ruch przesłony

    if(((digitalRead(10)==HIGH || digitalRead(9)==HIGH)&&(digitalRead(8)==LOW)) && pos< 180)
   
      {pos++;
      servo.write(pos);
      delay(15);}           //servo otwiera przesłone
      
    else
      {digitalWrite(2,LOW);} //servo nie działa
      
    if((digitalRead(10)==LOW && digitalRead(9)==LOW && digitalRead(7)==LOW) && pos>0)
      {pos--;
      servo.write(pos);
      delay(15);}           //servo zamyka przesłone
      
    else
      {digitalWrite(2,LOW);} //servo nie działa  
  }    

 

serwo dominator.png

Edytowano przez alshrom
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

(edytowany)
12 godzin temu, ethanak napisał:

Spróbuj nie robić servo.attach w setup, a dopiero po wciśnięciu przycisku.

Zmieniłem kod, ale nadal jest problem bo serwo po spełnieniu warunków na ruch wykonuje najpierw szybki ruch na pozycje określoną w linijce "int pos =0/120/150/(co wpisze). Na plus jest to, że jeżeli przerwę zasilanie w pozycji gdzie przesłona ma się nie ruszać to po ponownym uruchomieniu serwo nie wraca z automatu na pozycję 90 stopni. Czy problem nie jest taki, że moje tanie serwo po prostu nie ma pojęcia w jakim miejscu się znajduje i zawsze po utracie zasilania będzie wracać do jakieś bazy? Czy zastosowanie serwa cyfrowego coś zmieni?

Edytowano przez alshrom
Link do komentarza
Share on other sites

12 godzin temu, alshrom napisał:

Czy problem nie jest taki, że moje tanie serwo po prostu nie ma pojęcia w jakim miejscu się znajduje

Wręcz przeciwnie - nawet najtańsze serwo dokładnie (no, w miarę, zależy od stopnia taniości) wie w jakim miejscu się znajduje i do żadnej hipotetycznej "bazy" nie wraca. Problem w tym, że program po włączeniu zasilania nie wie, w jakiej pozycji znajduje się serwo i czyni sonie jakieś założenia nie zawsze zgodne z prawdą.

Jeśli nie przewidujesz wyłączania zasilania i zatrzymywania serwa gdzieś w połowie drogi - krańcówki wystarczą (któraś powinna być zawsze włączona) i na ich podstawie możesz stwierdzić, w jakiej pozycji serwo się znajduje. Jeśli jednak wyłączysz zasilania w połowie ruchu serwa - program zgłupieje, bo nie wie do jakiej pozycji ma przesunąć orczyk.

Owszem, istnieją serwa które "gadają" sobie z mikrokontrolerem, ale cena jest raczej niespecjalnie atrakcyjna.

Jedyna sensowna możliwość to poinformowanie programu o aktualnej pozycji serwa.

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

Niestety, ale jestem pewny, że będą występowały sytuacje utraty zasilania podczas wykonywania ruchu serwa. Rozumiem, że muszę napisać program w taki sposób by cały czas czytał i zapisywał w pamięci ostatnią pozycję serwa, a następnie przy ponownym odpaleniu na niej się bazował. Czyli jak aktualnie mam sytuacje, że serwo wraca do pozycji zadanej w komendzie- int pos =0; to ma to wyglądać  mniej więcej tak: int pos ="ostatnia zapamiętana pozycja".

Jeżeli dobrze zrozumiałem to prosiłbym o poradę w jakich komendach szukać rozwiązania/ o czym dokładnie poczytać.

Link do komentarza
Share on other sites

37 minut temu, alshrom napisał:

by cały czas czytał i zapisywał w pamięci ostatnią pozycję serwa

I w ten sposób wykończysz EEPROM. Musisz odczytywać rzeczywistą pozycję serwa (potencjometr na osi), a nie bazować na jakichś pamięciach.

W sumie chcesz zastosować serwo do czegoś, do czego nie jest przeznaczone. Czy naprawdę nie lepiej jakiś mały silniczek (choćby taki?) Wtedy masz tylko dwie krańcówki, (możesz je nawet podłączyć do silniczka przez diody żeby mieć pewność że silnik się wyłączył), mechanicznie układ będzie dokładnie taki jak z serwem, program się uprości...

Pomyśl!

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

Albo nawet zrobić poor-men servo czyli potencjometr obrotowy lub suwakowy (lub inny ulubiony czujnik położenia/odległości) podłączony gdzieś do mechaniki tej klapki. Wtedy program zawsze wie w jakieim stanie jest mechnika i nawet gdy obudzi się o 10 rano w stanie wskazującym, bez problemu zorganizuje się do poprawnego działania. Być może w najprostszym przypadku rzeczywiście wystarczą dwa wyłączniki krańcowe  (lub inne ulubione czujniki np. transoptory szczelinowe/odbiciowe, kontaktrony z magesikami itp). A zamiast standardowego serwa użyć popularnych obecnie serw tzw. 360°, sterowanych dokładnie tak samo, ale mających nieograniczony ruch w każdą stronę.

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

Bałem się to proponować, ale jeśli serwo jest rozbieralne (dwie/cztery małe śrubki w rogach?) to może to być strzał w dziesiątkę. Trzeba tylko uwążać przy pierwszych uruchomieniach kodu, bo nawet mały silnik z takim przełożeniem potrafi zmielić potencjometr i mechaniczne ograniczenia obrotu osi wyjściowej.

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

Myślałem raczej o podpięciu się do istniejącego obwodu (tzn. pozostawienia wewnętrznego sterownika serwa i tylko skorzystanie z potencjometru dodatkowo jako czujnika położenia dla Arduino).

 

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

Ale to nie chroni przed narowami serwa w stanach nieustalonych, np. po włączeniu zasilania, gdy jeszcze nie ma impulsów itp. Jeśli tego się nie boimy (albo posiadane serwo nie robi głupot w takich sytuacjach) to zdejmowanie napięcia z potencjometru do ADC wymaga jedynie dospawania jednego kabelka i zdjęcia ch-ki napięcia w funkcji kąta bo przecieżnie wiadomo, czy potencjometr jest rozpięty między Vcc i GNC. Świetny pomysł.

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

2 minuty temu, marek1707 napisał:

to nie chroni przed narowami serwa w stanach nieustalonych, np. po włączeniu zasilania, gdy jeszcze nie ma impulsów

Dlatego rozwiązanie z silnikiem wydaje mi się lepsze - bardziej naturalne. Szczególnie, że silniczek który znalazłem ma akurat taką prędkość obrotową (14 RPM) że idealnie by pasował do problemu (pół obrotu w ciągu 2 sekund), a wcale nie jest większy od serwa standard.

 

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

(edytowany)

Chyba wszystko zrozumiałem. Uznaję, że mam trzy opcję do wyboru:

1. Przerabiam serwo na silnik (lub kupuję serwo 360) , i wtedy serwo wykonuje ruch, gdy sygnał od arduino różni się od zablokowanego na potencjometrze (np. 90 stopni). W tym przypadku prędkość serwa będzie zależeć od różnicy między zadanym kątem, a  90 stopni.

2. Stosuję serwo wraz z zamontowanym enkoderem w postaci np. potencjometru. Wtedy po naciśnięciu przycisku mogę mu zadać komendę: wykonuj +1 stopień od wskazania potencjometru, w jakiś odstępach czasowych. I tutaj mam pytanie: czy istnieją serwa modelarskie, które mogą wysyłać sygnał do arduino nt. swojej aktualnej pozycji?

3. Stosuję silnik z przekładnią, którego obroty i kierunek mogę sterować np. za pomocą mostka typu H.

4 godziny temu, ethanak napisał:

 

W sumie chcesz zastosować serwo do czegoś, do czego nie jest przeznaczone. Czy naprawdę nie lepiej jakiś mały silniczek (choćby taki?)

Chciałem zastosować serwo, a nie silnik z przekładnią, dlatego że ma małe gabaryty, są wodoodporne, mają duże momenty i można łatwo sterować prędkością obrotową.

Z geometrii mojego układu wynika, że potrzebuję napędu, który wykona około 5 obr/min.

Edytowano przez alshrom
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.