Arduino - wykonanie jednego polecenia (bez pętli)

Tu można uprawiać dyskutanctwo ;-)

Moderatorzy: moderatorzy2014, moderatorzy

mrozilla
Posty: 219
Rejestracja: poniedziałek 12 maja 2014, 18:01
Lokalizacja: Polska

Arduino - wykonanie jednego polecenia (bez pętli)

Post autor: mrozilla »

Zaczynam dopiero korzystać z Arduino i nie mogę znaleźć rozwiązania prostego problemu. Chcę aby po włączeniu Arduino ramię serwa wykonało ruch do końca w jedną stronę po czym wróciło do pozycji początkowej i na tym zakończyło program, tak jakby wykonało np. otwarcie i zamknięcie jakiejś klapki.

Próbowałem przerobić kod, który powoduje, że ramię idzie do końca, po czym szybciej wraca do pozycji początkowej i ponownie wykonuje to samo.

Kod: Zaznacz cały

#include <Servo.h> //Biblioteka odpowiedzialna za serwa
 
Servo serwomechanizm;  //Tworzymy obiekt, dzięki któremu możemy odwołać się do serwa 
int pozycja = 0; //Aktualna pozycja serwa 0-180
int zmiana = 6; //Co ile ma się zmieniać pozycja serwa?
 
void setup() 
{ 
  serwomechanizm.attach(9);  //Serwomechanizm podłączony do pinu 9
} 
 
void loop() 
{  
  if (pozycja < 180) { //Jeśli pozycja mieści się w zakresie
    serwomechanizm.write(pozycja); //Wykonaj ruch
  } else { //Jeśli nie, to powrót na początek
    pozycja = 0;
  }    
  
  pozycja = pozycja + zmiana; //Zwiększenie aktualnej pozycji serwa
  delay(200); //Opóźnienie dla lepszego efektu                        
}
Po małej modyfikacji jedyne co udało mi się zrobić, że wykonuje ruch do końca ale już nie wraca do pozycji startowej.

Kod: Zaznacz cały

#include <Servo.h> //Biblioteka odpowiedzialna za serwa

Servo serwomechanizm;  //Tworzymy obiekt, dzięki któremu możemy odwołać się do serwa 
int pozycja = 0; //Aktualna pozycja serwa 0-180
int zmiana = 6; //Co ile ma się zmieniać pozycja serwa?
int blokada = 0;

void setup() 
{ 
 serwomechanizm.attach(9);  //Serwomechanizm podłączony do pinu 9
} 

void loop() 
{  
 if (pozycja < 180) { //Jeśli pozycja mieści się w zakresie
   serwomechanizm.write(pozycja); //Wykonaj ruch
 } else { //Jeśli nie, to powrót na początek
   blokada = 0;
 }    
 
 pozycja = pozycja + zmiana; //Zwiększenie aktualnej pozycji serwa
 delay(200); //Opóźnienie dla lepszego efektu                        
blokada = 1;
}
Nie wiem jak zrobić, żeby wykonało cały pierwszy kod i po powrocie do pozycji startowej program się zakończył. Dodam, że chodzi o wykonanie programu po włączeniu zasilania Arduino z zewnętrznego programatora (póki co czekam na moduł zegara dlatego to będzie najprostsze rozwiązanie) o określonej godzinie bez użycia żadnych przycisków, po prostu załącza się prąd, ramie wykonuje ruch w jedną stronę, najlepiej aby ze 2-3 sekundy po otwarciu odczekało po czym wykonuje ruch powrotny i kończy program, po około minucie programator czasowy odcina prąd i zadanie wykonane.
Po prostu określone zadanie wykonywane jest jeden raz, z tego co widziałem łatwo byłoby to zrobić dodając do projektu switch ale właśnie chodzi o to aby zrobić to bez żadnego switcha jedynie z czasem zamiast zewnętrznego programatora dodałbym moduł zegarka DS3231.

Może ktoś będzie w stanie jakoś rozwiązać ten problem?
Szymon
Posty: 992
Rejestracja: poniedziałek 06 wrz 2010, 09:18
Lokalizacja: Pruszków
Kontakt:

Re: Arduino - wykonanie jednego polecenia (bez pętli)

Post autor: Szymon »

Żeby zatrzymać wykonywanie programu, dodaj na końcu funkcji loop nieskończoną pętlę. Np. taką (ona nic nie robi, marnuje tylko prąd):

Kod: Zaznacz cały

while(1) {}
i po problemie ;)

Celowo nie daję gotowego pełnego kodu. Niestety, nie nauczysz się programować bez kombinowania i lepszego lub gorszego, ale samodzielnego rozwiązywania problemów.

PS. Czyżbyś robił tak zwane bezużyteczne pudełko? :)
mrozilla
Posty: 219
Rejestracja: poniedziałek 12 maja 2014, 18:01
Lokalizacja: Polska

Re: Arduino - wykonanie jednego polecenia (bez pętli)

Post autor: mrozilla »

Właśnie widzę, że nie jest kompletne, bo po dodaniu tego serwo przestaje działać, znaczy jeden ruch wykona, jeżeli jest w innej pozycji niż początek, wróci do początku i się zatrzymuje, nie wykonuje pełnego ruchu w jedną stronę i powrotu do pozycji 0.

Chcę zrobić taki bardzo prosty podajnik karmy, że po prostu ramie przesuwa się dzięki czemu odsuwa spód pojemnika i pokarm wypada ale niestety póki co albo macha póki jest zasilanie, albo nie działa :)

W ogóle wziąłem się za Arduino, bo chcę w jakiś sposób wyprowadzić telemetrię z Nazy do 9XR Pro przez Frsky D8R-II Plus, a to już bardziej skomplikowane.
Szymon
Posty: 992
Rejestracja: poniedziałek 06 wrz 2010, 09:18
Lokalizacja: Pruszków
Kontakt:

Re: Arduino - wykonanie jednego polecenia (bez pętli)

Post autor: Szymon »

Ok, to kolejna podpowiedź: wrzuć zawartość funkcji loop odpowiedzialną za ruch serwa (czyli w zasadzie całą) do pętli (pomyśl nad typem pętli i warunkiem jej zatrzymania - może użyjesz bezużytecznej do tej pory zmiennej o nazwie blokada?), a pod tą pętlą dodaj pętlę nic nie robiącą.
Tanner
Posty: 793
Rejestracja: wtorek 31 maja 2016, 20:08
Lokalizacja: Gdańsk/Kraków

Re: Arduino - wykonanie jednego polecenia (bez pętli)

Post autor: Tanner »

Dodaj na samym początku zmienną koniec=0, wszystko co masz w głównej pętli wsadź w if(koniec == 0){}.
Dodaj if (pozycja == 0) { koniec = 1; } aby ustawiło zmienną koniec wtedy kiedy trzeba ;)
Delay 200 możesz przenieść poza if(koniec==0), na początku żadna to różnica ale jak będzie po wszystkim to procek nie będzie się zajeżdżał.
Szper
Posty: 443
Rejestracja: piątek 11 gru 2015, 10:22

Re: Arduino - wykonanie jednego polecenia (bez pętli)

Post autor: Szper »

A wrzucić wszystko w "setup" co ma być 1x zrobione a do "loopa" nic nie dawać?
Syma X5C -> "Drewniak X5C"
S500 Black -> "Szlajacz" Black Snapper PRO L
GEPRC ZX5 190
I różne mikroby 1103, 1304...
Tanner
Posty: 793
Rejestracja: wtorek 31 maja 2016, 20:08
Lokalizacja: Gdańsk/Kraków

Re: Arduino - wykonanie jednego polecenia (bez pętli)

Post autor: Tanner »

Właśnie chodzi o to, że ma się wykonywać w kółko aż nie dojdzie do pozycji początkowej, a wtedy przestać na zawsze :)

Można też dać wszystko w:

robic = 1;
while(robic) {
tutaj wszystko co obecnie;
if(warunek do skonczenia) { robic = 0 }
}
Awatar użytkownika
StaryDzolero
Posty: 77
Rejestracja: czwartek 06 sie 2015, 09:44
Lokalizacja: Poznań

Re: Arduino - wykonanie jednego polecenia (bez pętli)

Post autor: StaryDzolero »

Chyba o coś takiego Ci chodzi,
idzie od 0 do 180 czeka 2 sekundy po czym wraca od 180 do 0 i wchodzi w tryb Power-Down :)
Do tego polecam https://github.com/rocketscream/Low-Power LowPower - wprowadzisz arduino w stan uśpienia, przy okazji oszczędzisz trochę na prądzie - bo z idle 30mA potrafi wejść w pobór ok 8uA i zatrzyma działanie kodu :) a w przyszłości jak dodasz zegar to tylko przerwania dodasz i masz usypianie i budzenie procka + wykonanie kodu i oszczędność energii :)

Kod: Zaznacz cały

#include <Servo.h>
#include <LowPower.h>

#define servoStep 6
#define servoPin 9
#define servoMin 0
#define servoMax 180

Servo sServo;
int sleepMode = 0;
int lifeCycle = 0;
int prevLifeCycle = 0;
int position = 0;

int calcNewPosition() {
    if (position <= servoMax && position >= servoMax) lifeCycle++;
    if (lifeCycle >= 2) return 0;
    return lifeCycle % 2 ? position - servoStep : position + servoStep;
}

void setup() { 
    sServo.attach(servoPin);
} 

void loop() {
    if (lifeCycle >= 2 && sleepMode == 0) {
        sleepMode = 1;
        LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); 
    } else if (lifeCycle < 2 && sleepMode == 0) {
        sServo.write(position);
        delay(200);
    }

    position = calcNewPosition();

    if (prevLifeCycle != lifeCycle) {
        prevLifeCycle = lifeCycle;
        delay(1800);
    }
}
Hexa Tarot 690__| Lisam LS210
Pioneer 1400____| Hubsan Q4
Hubsan h107d___| QAV250
Eachine QX90____| s500
i się rozrasta :)
mrozilla
Posty: 219
Rejestracja: poniedziałek 12 maja 2014, 18:01
Lokalizacja: Polska

Re: Arduino - wykonanie jednego polecenia (bez pętli)

Post autor: mrozilla »

Dziękuję za tak duże zainteresowanie, w między czasie dzięki pomocy @Szymon udało się stworzyć ostateczny kod, który spełnia swoje zadanie, a wygląda tak:

Kod: Zaznacz cały

#include <Servo.h> //Biblioteka odpowiedzialna za serwa
 
Servo serwomechanizm;  //Tworzymy obiekt, dzięki któremu możemy odwołać się do serwa 
int pozycja = 0; //Aktualna pozycja serwa 0-180
int zmiana = 5; //Co ile ma się zmieniać pozycja serwa?
 
void setup() 
{ 
  serwomechanizm.attach(9);  //Serwomechanizm podłączony do pinu 9
  serwomechanizm.write(0);
} 
 
void loop() 
{  
  /* czesc pierwsza - wychylenie serwa */
  while(pozycja < 180) { // dopoki pozycja jest mniejsza od 180
    pozycja = pozycja + zmiana; // zwieksz pozycje o zmiane
    if(pozycja > 180) pozycja = 180; // jesli wyszlismy poza zakrez maksymalny pozycji zredukuj do zakresu maksymalnego 
    serwomechanizm.write(pozycja); // wyslij nowa pozycje na serwo
    delay(50); // poczekaj dla lepszego efektu
  }
  
  /* czesc druga - powrot serwa */
  serwomechanizm.write(0);
  delay(400); // byc moze ten delay nie jest potrzebny, ale nie zaszkodzi poczekac
  serwomechanizm.detach(); // zluzowanie serwa  
  /* czesc trzecia */
  while (true) {} // nic nie rob - 
}
ODPOWIEDZ