• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Sleep zliczanie czasu włącz pin Attiny
#1
Witam

Układ zasilany z baterii
Czy mógłby ktoś podpowiedzieć jak uzyskać taką funkcję w sleep:
Attiny wybudzanie z przerwania włącz pin zrób coś i spać. Ponowne wybudzanie z przerwania nie uruchamia pinu przez najbliższe 5min dopiero po tym czasie jeśli wystąpi przerwanie.

Z góry dziękuję
 
#2
To co byś chciał jest spodziewanym zachowaniem, więc może po prostu pokaż schemat i kod, opisz jak powinno działać vs jak działa.
Edit
Przy drugim czytaniu dotarło do mnie więcej, że nic nie masz i że wybudzanie jest przez INT.
Ustawiasz wybudzanie przez WDT z wyłaczonym INT0, za każdym wybudzeniem zwiększasz zmienną, jak osiągnie wymagany czas to usypiasz bez WDT, a tylko z INT0.
http://www.gammon.com.au/forum/?id=11497 tu jest wiele użytecznych rzeczy opisanych. Pewnie są też inne sposoby, można nie wyłączać w uśpieniu timera sprzętowego, ale to większe zużycie energii, więc ja używałem tylko tych z WDT i INT0.
 
#3
Kod:
/*  Sleep Pobór pradu 3.8 uA.
*  Ustawienie Zegara INTERNAL 5MHz.
*  Arduino 1.8.13
*/

#include <avr/io.h>
#include <math.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

int blok = 0;

ISR(PORTA_PORT_vect)
{
  if (bitRead(PORTA.INTFLAGS, 2)) {  // RTC TIMER Adapter Pin 18.

    PORTA.INTFLAGS = PORT_INT2_bm; //reset flagi przerwania
    blok = 3; // RTC TIMER
  }
  if (bitRead(PORTA.INTFLAGS, 6)) { 

    PORTA.INTFLAGS = PORT_INT6_bm; //reset flagi przerwania

    blok = 2;
  }
  if (bitRead(PORTA.INTFLAGS, 5)) { 

    PORTA.INTFLAGS = PORT_INT5_bm; // reset flagi przerwania

    blok = 1;
  }
}
void przebudzenie() {
  PORTB.DIR |= 1 << 1;  // Ustawia jako Wyjście.
  PORTB.DIR |= 1 << 5;  // Ustawia jako Wyjście.
 
  PORTB.OUTCLR = 1 << 1; // Podanie GND na PB1.
  PORTB.OUTCLR = 1 << 5; // Podanie GND na PB5.
  delay(1000);
}
void spanie() {
  PORTB.DIRCLR = 1 << 1; // Ustaw jako wejscie
  PORTB.DIRCLR = 1 << 5; // Ustaw jako Wejscie

  PORTB.PIN1CTRL = 1 << PORT_PULLUPEN_bp; // odłączenie GND
  PORTB.PIN5CTRL = 1 << PORT_PULLUPEN_bp; // odłączenie GND

  //-- Idź Spać -------------------------------------------------------------------------------------------------------
  sleep_cpu();
}
void setup() {

  //--- konfiguracja trybu sleep -------------------------------------------------------------------------------------
  SLPCTRL.CTRLA = 1 << SLPCTRL_SEN_bp      /* Sleep enable: enabled */
                  | SLPCTRL_SMODE_STDBY_gc; /* Standby Mode */

  // PA2 Konfiguracja przerwania Adapter Pin 18
  PORTA.DIRCLR |= 1 << 2; //ustwienie bitu jako input
  PORTA.PIN2CTRL  = PORT_ISC_FALLING_gc | 1 << PORT_PULLUPEN_bp; // ustawienie pullupa i typu wyzwalania zboczem opadajacym
 
  // PA6 konfiguracja przerwania Adapter Pin4
  PORTA.DIRCLR |= 1 << 6; //ustwienie bitu jako input
  PORTA.PIN6CTRL  = PORT_ISC_FALLING_gc | 1 << PORT_PULLUPEN_bp; // ustawienie pullupa i typu wyzwalania zboczem opadajacym
 
  // PA5 konfiguracja przerwania Adapter Pin3
  PORTA.DIRCLR |= 1 << 5; //ustwienie bitu jako input
  PORTA.PIN5CTRL  = PORT_ISC_LEVEL_gc | 1 << PORT_PULLUPEN_bp; // ustawienie pullupa i typu wyzwalania stanem niskim

  CPUINT.CTRLA &= ~CPUINT_LVL0RR_bm; // Włącz Przerwania
  CPUINT.LVL0PRI = PORTA_PORT_vect_num; // Zmiana priorytetu przerwan.

  for (uint8_t i = 0; i < 8; i++) {    //  Ustaw Wszyskie Piny w trybie niskiego poboru mocy
    *((uint8_t *)&PORTA + 0x10 + i) |= 1 << PORT_PULLUPEN_bp;
  }

  for (uint8_t i = 0; i < 8; i++) {    //  Ustaw Wszyskie Piny w trybie niskiego poboru mocy
    *((uint8_t *)&PORTB + 0x10 + i) |= 1 << PORT_PULLUPEN_bp;
  }
  for (uint8_t i = 0; i < 8; i++) {    //  Ustaw Wszyskie Piny w trybie niskiego poboru mocy
    *((uint8_t *)&PORTC + 0x10 + i) |= 1 << PORT_PULLUPEN_bp;
  }
  PORTMUX.USARTROUTEA |= PORTMUX_USART1_ALT1_gc;
  Serial1.swap(1);
  Serial1.begin(9600); 

  sei();    //włączenie przerwań
}
void loop() {

  przebudzenie();
 
  switch (blok) {
    case 1:
      Serial1.write("otw"); 
      break;
    case 2:
      Serial1.write("zam"); 
      break;
    case 3:
      Serial1.write("rap");
  }
  blok = 0;
  delay(500);
  spanie(); // Idź Spać.
}
Witam dziękuje za wskazówki w temacie. Procesor to Attiny1626.  Nie jestem jakimś specem w programowaniu hobyystycznie program napisałem na bazie tego co przeczytałem, znalazłem i wiedzy którą cały czas staram się zdobywac na kursach itp.

Program działa dobrze Sam Procesor usypia się do 130nA.
Wybudzanie asynchroniczne na dwóch przerwaniach PA2 i PA6 i zwykłe  PA5.

Jeśli chciałbym uruchamiać pin PB1 jak pisałem wcześniej wybudzenie z przerwania włącza Pin PB1 robi cos idzie spać i ponowne wybudzenie z przerwania nie uruchomi pinu PB1 przez najlbliższe 5min, tylko jak minie ten czas i nastapi kolejne wyzwolenie z przerwania to muszę zastosować WDT? Nigdy nie używałem WDT będe musiał o nim poczytać. Eprom by tu pomógł jakby zapisywać czas? Będę bardzo wdzieczny za jakieś wskazówki jak najprościej i skutecznie to zrobić.
 
#4
Przeczytaj i potrenuj kody w linku. Ja Ci nic innego nie dopowiem, bo moja wiedza jest w tym zakresie stamtąd.
A niestety nie będzie to do końca rozwiązaniem Twojego problemu. Masz nowy uC, a to co napisałem opiera się na doświadczeniach z Atmega328p i Attiny 85 (i podobnych z ich epoki).
I tu nie było tak, że z WDT nic nie wybudzi uC przez godzinę bo tak oczekujesz mieć czas ignorowania przerwań zewnętrznych. WDT można ustawić w AVR typowo na max 8s, typowe wybranie czasu wygląda tak:
wdt_enable(WDTO_4S);
// WDTO_15MS
// WDTO_30MS
// WDTO_60MS
// WDTO_120MS
// WDTO_250MS
// WDTO_500MS
// WDTO_1S
// WDTO_2S
// WDTO_4S
// WDTO_8S
Czyli przy uśpieniu np. na 120s wybierasz największy dzielnik tej liczby, tu 4s, wyłączasz wybudzenie od przerwania zewnętrznego usypiasz uC, po wybudzenie zliczasz cykle uśpień i usypiasz ponownie, przy 30 wybudzeniu wyłączasz WDT i usypiasz z już aktywnym wybudzeniem od przerwania zewnętrznego, przy pierwszym takim wybudzenie ponawiasz cykl zerując zmienne i znowu przełączając na WDT. Czas można też zmieniać, można ustawić x *8 + y *4 + z *1s. Ten czas jest przybliżony, zależny od temperatury i dokładności oscylatora WDT.
I z WDT zużycie energii jest większe. Jak masz zewnętrzny timer to może on jest w stanie wybudzać uC nawet rzadziej, a przy okazji pobór prądu w uśpieniu bez WDT będzie mniejszy.
Natomiast zestaw dostępnych opcji może być nieco inny w tym Attiny, niestety pozostaje wertowanie forów o tym konkretnym uC lub wgryzanie się w 500 stronicowy datasheet tego procka. Pobieżne przejrzenie tego PDF insynuuje podobne opcje, też jest zakres WDT do 8s, Ale nie wiem czy te funkcje są w ogóle dostępne w Arduino. Nawet jeśli, to nie miałbym jak tego zweryfikować i przetestować, bo go nie mam.
 
#5
kaczakat dzięki za podpowiedzi.
To prawda proc jest nowy i jest mało informacji na ten temat używam go od jakiegoś czasu i uważam że to jest rewelka powoli wgryzam się w temat nowych fajnych możliwości ma full długo by pisać. Datasheet już czytałem cały po kilka razy?
Chyba sam sobie odpowiem posiada wbudowany RTC. Spr i działa wybudza proc z uśpienia, kiedy zadeklaruje programowo RTC to pobór prądu z 130nA wzrasta tylko do 930nA w trybie sleep. Nie użyłem tego zegara że względu wiadomego że jest nie dokładny bo wiadomo korzysta z wew oscylatora, ale jeśli chcemy żeby wybudził się np co 3dni cyklicznie to jak najbardziej wtedy czas będzie się rozjeżdżał, ale zegar będzie wybudzal proc cyklicznie pobierając przy tym 930nA w trybie sleep.
Licznik czasu rzeczywistego jest jak WDT w trybie przerwań, który jest w klasycznym AVR. W tych nowych seriach WDT może tylko zresetować urządzenie. Przerywanie w określonym czasie odbywa się teraz za pomocą RTC i PIT.
Dziala tak jak chciałem rejestr RTC PIT załatwił sprawę.Trzeba używać PIT, ponieważ jest to jedyne przerwanie czasowe, którego możemy użyć w trybie Power Down.
 
#6
Dzięki za podanie rozwiązania. Też tu wszedłem szukając pomocy i samo spisanie problemu pomaga na tyle, że jak dotąd to wystarczało. Czasami rozwiązanie przychodzi do głowy samo tuż po kliknięciu przycisku "opublikuj post".
 
  


Skocz do:


Przeglądający: 1 gości