Arduino Polska Forum

Pełna wersja: Opóźnienie działania arduino oraz 3 serwo.
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Witam,

Jak w temacie chciałbym opóźnić działanie arduino oraz serwo kolejno na 24, 48 i 72h. Po każdym cyklu arduino przebudzałoby się i aktywowało funkcję serwo. Zależy mi aby cały układ działał przez 3 dni na 6 bateriach AA, dlatego chce zastosować opóźnienie i wybudzenie. Widziałem wiele bibliotek odpowiedzialnych za to, ale nie wiem, z której skorzystać. Jako osoba początkująca prosiłbym o ukierunkowanie w jaką stronę zmierzać. 
Pozdrawiam.
W jaką stronę zmierzać?
Ano w taką, która najbardziej odpowiada Twoim oczekiwaniom.
Chcesz wybudzać procesor przerwaniem z timera, więc masz do wyboru cztery tryby pracy.
IDLE, ADC Noise Reduction, Power-save, Extended Standby.
Najlepszym wyborem, według mnie, jest tryb Power-save.

Ja bym napisał tak:
Kod:
#include <avr/sleep.h>
#include <avr/power.h>
volatile int licznik=0;

ISR(TIMER1_OVF_VECT)
{
  licznik++;
}

void dobranoc()
{
 set_sleep_mode(SLEEP_MODE_PWR_SAVE);
 
 sleep_enable();
 power_adc_disable();
 power_spi_disable();
 power_timer0_disable();
 power_timer2_disable();
 power_twi_disable();  

 sleep_mode();
 
 sleep_disable();

 power_all_enable();
}

void setup()
{
 TCCR1A=0x00;
 TCNT1=0x0000;
 TCCR1B=0x05;
 TIMSK1=0x01;
}

void loop()
{
 
 dobranoc();
 if(licznik==21600)
 {
   funkcja_obslugi_serwaomechanizmu();
   dobranoc();
 }
 if(licznik==43200)
 {
   funkcja_obslugi_serwaomechanizmu();
   dobranoc();
 }
 if(licznik==64800)
 {
     licznik = 0;// po 72 godzinach resetujemy licznik
   funkcja_obslugi_serwaomechanizmu();
   dobranoc();
 }
}
void funkcja_obslugi_serwaomechanizmu(){
   // tutaj napisz co ma robic serwo
}


Tryb zegara jest tak ustawiony, żeby resetował się co miej więcej 4 sekundy.
Po tym czasie daje nam przerwanie TIMER1_OVF_VECT i inkrementuje się zmienna licznik.
Gdy procesor wyjdzie z uśpienia 21600 razy, to oznacza, że minęło 24 godziny i wykonujemy funkcję obsługi serwa i idziemy spać.
ITD...
Samo usypianie niewiele da gdy na PCB znajdują się układy, których nie możesz usypiać jak konwerter USB-USART. Należałoby go wylutować. Kolejnym problem są stabilizatory. Czy potrzebujesz 3,3V? Nie to wywal go. Stabilizator 5V i baterie AA? Gdybyś wybrał akumulatory, które mają ok 1,2V to wywalasz stabilizator 5V.

Wracając do usypiania. Zastosuj głębokie uśpienie (uA poboru prądu) i wybudzanie od watchdoga. Ustaw przerwania od watchdoga, dzięki czemu uC nie będzie resetowany. Czasy przerwań od WDG nie są zbyt precyzyjne, jeśli mają być użyj timera 2 w trybie asynchronicznym (sprawdź czy T2 w uC może pracować z zewnętrznym kwarcem, w Mega2560 tak, w Mega328 - nie pamiętam).
Dzięki za odpowiedź,
Widzę, że usypianie dotyczy konkretnie arduino, a co z serwo? Jedyną opcją żeby zaoszczędzić energię i zapodać ją do serwo tylko kiedy będzie miała wykonać się funkcja jest budowa jakiegoś prostego przekaźnika?
(25-04-2018, 09:26)killa8boll napisał(a): [ -> ]co z serwo? Jedyną opcją żeby zaoszczędzić energię i zapodać ją do serwo tylko kiedy będzie miała wykonać się funkcja jest budowa jakiegoś prostego przekaźnika?
Zamiast przekaźnika lepiej dać MOSFET. Trzeba by zbadać jaki układ steruje silnikiem w serwie. Może ma wejście wprowadzające w obniżony pobór prądu. Identyfikacja układu może być trudna bo serwo pewnie od "żółtych".
Arduino w trybach Power-down oraz Power-save, przy wyłączonych peryferiach jak w moim kodzie, pobiera prąd około 37mA, przy czym sama atmega zjada wówczas 6,5μA, więc jest się o co bić.
No ale ufając, że płytka Arduino służy jedynie do prototypowania, to myślę, że ostateczna wersja urządzenia będzie gołą atmegą, zasilaną baterią ze StepUpa.
Wszystko jasne, wielkie dzięki za pomoc.
Napotkałem na problem z proponowanym wyżej programem z dołączonymi moimi funkcjami. Mianowicie nawet po zmniejszeniu wartości z 24/48/72h do kilku minut obrót serwo nie wykonuje się. Nie jestem w stanie znaleźć problemu. Prosiłbym o pomoc w działaniu programu:

#include <avr/sleep.h>
#include <avr/power.h>
volatile int licznik=0;
#include <HID.h>
#include <Narcoleptic.h>
#include <Servo.h>
#include <time.h>

Servo myservo1; // serwo nr 1
Servo myservo2; // serwo nr 2
Servo myservo3; // serwo nr 3

int pos = 0;

ISR(TIMER1_OVF_vect)
{
licznik++;
}

void dobranoc()
{
set_sleep_mode(SLEEP_MODE_PWR_SAVE);

sleep_enable();
power_adc_disable();
power_spi_disable();
power_timer0_disable();
power_timer2_disable();
power_twi_disable();

sleep_mode();

sleep_disable();

power_all_enable();
}

void setup()
{

myservo1.attach(9); // serwo nr 1, pin 9
myservo2.attach(8); // serwo nr 2, pin 8
myservo3.attach(7); // serwo nr 3, pin 7

TCCR1A=0x00;
TCNT1=0x0000;
TCCR1B=0x05;
TIMSK1=0x01;
}

void loop()
{

dobranoc();
if(licznik==21600)
{
funkcja_obslugi_serwaomechanizmu1();
dobranoc();
}
if(licznik==43200)
{
funkcja_obslugi_serwaomechanizmu2();
dobranoc();
}
if(licznik==64800)
{
licznik = 0; // po 72 godzinach resetujemy licznik
funkcja_obslugi_serwaomechanizmu3();
dobranoc();
}

}
void funkcja_obslugi_serwaomechanizmu1(){
for (pos = 90; pos <= 180; pos += 1) { //obrot z pozycji 90 stopni do 180
myservo1.write(pos);
delay(15); // szybkosc obrotu o 90 stopni
}
for (pos = 180; pos >= 90; pos -= 1) { //obrot z pozycji 180 stopni do 90
myservo1.write(pos);
delay(25); // szybkosc powrotu o 90 stopni

}
}
void funkcja_obslugi_serwaomechanizmu2(){
for (pos = 90; pos <= 180; pos += 1) { //obrot z pozycji 90 stopni do 180
myservo1.write(pos);
delay(15); // szybkosc obrotu o 90 stopni
}
for (pos = 180; pos >= 90; pos -= 1) { //obrot z pozycji 180 stopni do 90
myservo1.write(pos);
delay(25); // szybkosc powrotu o 90 stopni

}
}
void funkcja_obslugi_serwaomechanizmu3(){
for (pos = 90; pos <= 180; pos += 1) { //obrot z pozycji 90 stopni do 180
myservo1.write(pos);
delay(15); // szybkosc obrotu o 90 stopni
}
for (pos = 180; pos >= 90; pos -= 1) { //obrot z pozycji 180 stopni do 90
myservo1.write(pos);
delay(25); // szybkosc powrotu o 90 stopni
}

}
Sprawdź czy program uruchamia funkcje.
Na przykład, zamiast:

Kod:
void funkcja_obslugi_serwaomechanizmu1(){
for (pos = 90; pos <= 180; pos += 1) { //obrot z pozycji 90 stopni do 180
myservo1.write(pos);
delay(15); // szybkosc obrotu o 90 stopni
}

Wpisz

Kod:
void funkcja_obslugi_serwaomechanizmu1(){
Serial.println("Wybudzenie 1");
}

Sprawdź, czy te pętle poruszają serwem.
Dopisz do funkcji setup
Kod:
for (pos = 90; pos <= 180; pos += 1) { //obrot z pozycji 90 stopni do 180
myservo1.write(pos);
delay(15); // szybkosc obrotu o 90 stopni
Powinno ruszyć serwem przed wejściem w śpiączkę.
A cha, jeszcze taka mała dygresja: nie używaj zmiennych globalnych dla licznika pętli.
Globalne, to zło. Deklaruj sobie zmienne tymczasowe.