logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Reanimacja i modyfikacja świeczek LED na Attiny13a - problem z poborem prądu tryby SLEEP

kdgp1491 26 Mar 2023 11:02 873 10
REKLAMA
  • #1 20508960
    kdgp1491
    Poziom 3  
    Mam w domu kilka świeczek podobnych do tych z obrazka
    Reanimacja i modyfikacja świeczek LED na Attiny13a - problem z poborem prądu tryby SLEEP
    Po czasie prawie wszystkie przestały działać - zniszczone ścieżki na płytce od wilgoci, przerdzewiałe styki włącznika. Dodatkowo świece mają tylko ruchomy płomień, a świecą statycznie. Nie było też żadnego czujnika światła, tylko ręczne włączanie
    Postanowiłem je reanimować i lekko zmodyfikować. Wstawiłem układ na Attiny 13a działający tylko w ciemności - fofotranzystor na wejściu, a czas świecenia uzależniłem od długości dnia. Oprócz ruchomego płomienia dioda led imituje zmianę jasności świecy przez losową zmianę wypełnienia. Dodatkowo wstawiłem czujnik rozładowania baterii, który po spadku napięcia co kilka sekund losowo generuje impuls.
    generalnie wszystko działa ale mam problem z trybem sleep_mode. Po załączeniu układ pobiera około 5nA ale po chwili jest 0,161mA
    Program zajmuje 99,8% pamięci.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #2 20509039
    excray
    Poziom 41  
    Używając rejestru DIDR0 wyłącz cyfrową część wejść analogowych. Jak wygląda sprawa z pullupem dla fotorezystora? Jeśli możesz dołącz najlepiej schemat.
  • REKLAMA
  • #3 20509309
    kdgp1491
    Poziom 3  
    Prawdopodobnie źle używam zmiennych volatile przerwa. Zmienna ta jest chyba gubiona. Jeśli zamiast if (przerwa == 0) wpiszę jakąkolwiek inną wartość układ pobiera cały czas te 5 nA
  • REKLAMA
  • #4 20509494
    ex-or
    Poziom 28  
    Nie sposób skutecznie przeanalizować tego programu - dwa zagmatwane wątki, prawdopodobny wyścig. Inne błędy: wykorzystanie opóźnień (w tym w przerwaniu) i pętli busy waits zamiast przerwania.
    Ale mniejsza z tym. Co więc widać? ADC nie jest wyłączany przed uśpieniem.
  • #5 20509924
    kdgp1491
    Poziom 3  
    Kod raczej mało skomplikowany - program główny to kilka pętli do losowej jasności diody i włączania cewki od ruchomości płomienia z opóźnieniami . Być może są tam błędy ale działa wg oczekiwań nie ma to żadnego wpływu na mój problem. Uruchamiany jeśli wykonuj == true. To czy program ma się wykonywać uzależnione od wartości w przerwaniu.
    Opóźnienia w przerwaniu wstawiłem bo miałem problem przy odczytywaniu ADC jeden po drugim.

    Według mnie ADC jest wyłączany przed uśpieniem.
    Problemem jest to, że wartość "przerwa" gubi się i przy sprawdzeniu = 0 i program przechodzi do odczytów ADC w przerwaniu.

    Doceniam Twoją odpowiedź, że ADC nie jest wyłączany ale jednak prosiłbym o info jak to zmienić
  • REKLAMA
  • Pomocny post
    #6 20510290
    bart-projects
    Poziom 29  
    Założenia Watchdoga są takie, że jeśli włączysz przerwanie od niego to za pierwszym okresem nie zresetuje procesora tylko wejdzie w obsługe przerwania, ale on w tym przerwaniu skasuje bit WDTIE i już za drugim okresem zrestartuje procesor.

    Żeby Watchdog stale miał włączone przerwanie to trzeba to w kółko ustawiać.

    Teoretycznie nie powinno się z powrotem bitu WDTIE ustawiać w przerwaniu. Powinno się go ustawiać gdzieś w swoim programie tak by zachować opcję resetu gdy program naprawdę stanie.

    Jesli chcesz oszczedzać prąd podczas snu uC to ADC powinieneś każdorazowo wyłaczać przed komendą "sleep_mode(); " tak jak inne zabiegi jesli przewidujesz.

    Ustawianie bitu WDTIE musisz wstawić gdzies do pętli While(1) bo nawet jak "wykonuj==true" to Watchdog pracuje już kolejny cykl i za chwilę zresetuje Tobie procesor.

    Pamiętaj że po komendzie "sleep_mode(); " procesor po załatwieniu przerwania zacznie wykonywanie programu dalej od następnej linijki czyli u Ciebie "PORTB&= ~((1<<DIODA) | (1<<CEWKA) | (1<<WEAK)); " i zrobi dopiero pętlę do "While(1) "
    A jesli kręci się w pętli While(1) to juz na pewno tego "ADCSRA &= ~(1<<ADEN); " nie zrobi przed pójściem spać ;)

    BTW. Po ustawieniu bitu zmian WDCE masz tylko cztery takty zegara na ustawienie WDE, WDP1 i WDP2 więc wątpię, że się to Tobie tam udaje :D
  • #7 20510748
    JacekCz
    Poziom 42  
    kdgp1491 napisał:
    Kod raczej mało skomplikowany


    Kod jest toksyczny. W pełni zgadzam się z @exor

    Kod, taki jak ten, jeśli wygląda źle, na mocy statystyki ma (liczne) błędy.
    Delayów w procedurze przerwania nie da się obronić.
    NIE DA SIĘ zapewnić zdebugowania kodu na przerwaniach / współbieżnego, jeśli fundamentem nie będzie kod zgodny ze sztuką profesjonalną
  • #8 20510764
    bart-projects
    Poziom 29  
    Się tu kolega @JacekCz chyba zapędził. Ten uC ma 64B SRAM i 1KB FLASH.
    To co tu się "próbuje dziać" to to, że Pomiary ADC są robione w przerwaniu co czas okreslony Watchdogiem, ale to rozwiązanie od razu wybudza też uC z głębokiego snu POWERDOWN (jeśli w nim był) i tylko Watchdog, PCINT albo LOW_LEVEL może uC z tego wybudzić uC. Tak więc po co dokładać tu rozwiazanie na jakimś timerze, skoro WDT i tak się przyda a dokładnośc czasowa nie ma tu znaczenia. Pamiętajmy że mamy się zmieścić w 1KB FLASH.

    ADC w AVR jesli był wczesniej wyłączony potrzebuje chwili by wstać, innej chwili po zmianie kanału MUX, a tu wstaje po wyłaczeniu przed uśpieniem.

    Na pewno można to napisać inaczej i ja inaczej bym to na pewno rozwiązał. Niemniej wskazałem błedy a każdy swoje godziny nad nauką powinien poswięcić sam więc gotowca nie podam.
  • #9 20512457
    JacekCz
    Poziom 42  
    bart-projects napisał:
    Ten uC ma 64B SRAM i 1KB FLASH.



    Jaki to ma związek z jakością kodu ?
  • #10 20521254
    kdgp1491
    Poziom 3  
    Postarałem się trochę "ucywilizować" ten kod. Mam nadzieję, że teraz wygląd to bardziej po ludzku.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Po tej zmianie mam odwrotny problem problem bo teraz z kolei nie wychodzi z trybu sleep_mode.


    Próbowałem zmienić tryb_sen na
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    ale przy tym system prawdopodobnie się sam resetuje bo wymazuje mi zmienne w przerwaniu.

    Próba zapisania zmiennych do eeprom nie wchodzi niestety w grę bo brakuje pamięci do tej operacji

    Jeśli chodzi o jakość kodu to zdaje sobie sprawę, że może wyglądać na beznadziejny - pierwszy raz w życiu coś takiego tworzę opierając się na internecie. Więc jeśli macie jeszcze ochotę po mnie jeszcze trochę "poujeżdżać" to proszę o krytykę ale ze wskazaniem o robię źle.
  • Pomocny post
    #11 20523351
    WojtasJD
    Poziom 43  
    https://www.nongnu.org/avr-libc/user-manual/pgmspace.html
    Dodaj const przed: uint8_t randomvals[] PROGMEM

    Częstotliwość zegara ADC (1,2 MHz / 64 = 18,75 kHz) za niska:
    ATtiny13A - tinyAVR® Data Sheet - 14.5 Prescaling and Conversion Timing napisał:
    By default, the successive approximation circuitry requires an input clock frequency between 50 kHz and 200 kHz to get maximum resolution. If a lower resolution than 10 bits is needed, the input clock frequency to the ADC can be higher than 200 kHz to get a higher sample rate.


    Wrzuć schemat z wartościami elementów - wartości dzielnika napięcia przez który mierzysz napięcie np. baterii nie są obojętne bo:
    ATtiny13A - tinyAVR® Data Sheet - 14.8 Analog Input Circuitry napisał:
    The ADC is optimized for analog signals with an output impedance of approximately 10 kΩ or less. If such a source is used, the sampling time will be negligible. If a source with higher impedance is used, the sampling time will depend on how long time the source needs to charge the S/H capacitor, with can vary widely. The user is recommended to only use low impedant sources with slowly varying signals, since this minimizes the required charge transfer to the S/H capacitor.


    Kolejne parę bajtów zaoszczędzisz jak ustawisz ADSCRA raz na początku a w funkcjach pomiaru napięcia zamiast ADCSRA = 0; daj ADCSRA &= ~(1<<ADEN);

    https://ww1.microchip.com/downloads/en/DeviceDoc/ATtiny13A-Data-Sheet-DS40002307A.pdf 10.4.3
    skoro początkowa wartość bitów DDRB = 0b00000000 to po co na początku main() zerujesz:
    DDRB &= ~((1<<POMIAR) | (1<<POMIAR_N)) ; //Ustawienie wejść ADC

    Na końcu kodu chyba niechcący "znakówka":
    if (slaba = 1 && lval1 > 220) PORTB|= (1<<WEAK);

    BTW: czy max_c nie powinna być volatile a val_F niekoniecznie?
    Dwie zmienne jako uint32_t to marnotrawstwo.

    No i wywołanie sleep_mode() z ISR to chyba niezbyt dobry pomysł:
    ATtiny13A - tinyAVR® Data Sheet - 4.7 Reset and Interrupt Handling napisał:
    When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled.



    bart-projects napisał:
    BTW. Po ustawieniu bitu zmian WDCE masz tylko cztery takty zegara na ustawienie WDE, WDP1 i WDP2 więc wątpię, że się to Tobie tam udaje
    Też tak kiedyś wyczytałem a tu:
    https://www.avrfreaks.net/s/topic/a5C3l000000UanuEAC/t155266
    http://ww1.microchip.com/downloads/en/AppNotes/doc2551.pdf
REKLAMA