www.swiatelka.pl  Strona Główna www.swiatelka.pl
...czyli forum miłośników światełek... ;-)

FAQFAQ  SzukajSzukaj  UżytkownicyUżytkownicy  GrupyGrupy
RejestracjaRejestracja  ZalogujZaloguj  AlbumAlbum  DownloadDownload
Google

 Ogłoszenie 
...UWAGA...NOWI UŻYTKOWNICY!!! ... brak słowa powitania w waszym pierwszym poście będzie równoznaczny z usunięciem posta i ostrzeżeniem. NA TYM FORUM CENIMY SOBIE KULTURĘ OSOBISTĄ!!! Lektura obowiązkowa: LINK

UWAGA
AKTUALIZACJA regulaminu działu handlowego > KLIK

Poprzedni temat «» Następny temat
Kondensator jako pamięć
Autor Wiadomość
Pyra 


Pomógł: 570 razy
Dołączył: 02 Sie 2009
Posty: 8533
Skąd: Gądki
Wysłany: 07-02-2014, 17:27   Kondensator jako pamięć

Witam
Jak wiadomo, podstawowym problemem przy rozpoznawaniu klików, jest trwałość pamięci eeprom. Analizując swoje doświadczenia z użytkowania latarek jak i użytkowników ,mniej zaawansowanych "światełkowo" zauważyłem, że zmiana trybów, nie jest wcale tak chętnie używana, a najczęściej, ustawiony jest jeden uniwersalny tryb wykonujący czarną robotę.
Większość procedur rozpoznawania klików, wykorzystuje zapis do eeprom po włączeniu latarki, następnie po jakimś czasie zapis jest zmieniany. Jeśli program przy starcie trafi na zapisaną komórkę eepromu, traktuje to jako sygnał do zmian. Problem polega na tym, że w czasie normalnej eksploatacji, mamy dwa zapisy do eepromu. Oczywiście można stosować sposoby na rozłożenie zapisu na wiele komórek itp. W zasadzie to zapis do komórki nie jest szkodliwy, a tylko jej skasowanie.
Ja postanowiłem pójść inną drogą i stworzyć pojedynczą komórkę RAM ;) . Co daje takie rozwiązanie, otóż zapisy do eepromu, dokonywane są tylko w przypadku wykrycia kliku. Zwyczajne włączenie latarki nie wprowadza żadnych zmian do pamięci, tak więc mamy małą oszczędność pamięci.
Zasada pracy mojego rozwiązania jest bardzo prosta. Po starcie procesora, program sprawdza, czy na kondensatorze, występuje określone napięcie. Jeśli napięcie na kondensatorze jest, oznacza to, że przerwa w zasilaniu była bardzo krótka, czyli wystąpił klik, co jest sygnałem do wprowadzenia zmian... Co nam to daje, a no możemy teraz zmieniać tryby pojedynczym klikiem. :idea:
Jeśli program podczas startu nie stwierdzi obecności napięcia na kondensatorze, przechodzi dalej bez ingerencji w parametry. Skąd jednak napięcie na kondensatorze? Otóż zaraz po sprawdzeniu, obecności napięcia na pinie, jest on podciągany do plusa. Przy stosowanej pojemności około 1µF i rezystancji podciągającej procesora w okolicach kilkudziesięciu kiloomów (około 60k) bardzo szybko mamy napięcie zasilania na kondensatorze.
Problemem jednak okazało się wykrycie napięcia, mimo iż rezystancja wejściowa pinów to przedział megaomów, to zwykłe wykrycie stanu okazało się niewystarczające. Zmiana kondensatora na większy, była by bezcelowa, w związku rezystancją podciągającą. Nie chciałem do ładowania używać ustawiania stanu wysokiego po zmianie portu na wyjście, gdyż mogło by to przeciążyć port. Dodanie dodatkowego rezystora, też odrzuciłem jako mało praktyczne w realizacji.
Aby uprościć realizację przeróbki, postanowiłem wykorzystać jako pady lutownicze "gwiazdki" służące pierwotnie do zmiany grupy trybów. Czasem zdarzają się driverki, mające przygotowane pady do lutowania zworek, tu będzie jeszcze łatwiej.

Tak to wygląda w implementacji, jak widać kondensator w rozmiarze 805 jest wlutowany pomiędzy gwiazdką a minusem - masą.
Teraz przyszedł czas na rozwiązania programowe. Skoro zwykłe sprawdzenie pinu jest niewystarczające, to przecież mamy do dyspozycji przetwornik ADC, którym możemy wykryć naprawdę niskie napięcia.
Napisałem bardzo prosty program, który jest działający, jednak za względu na pewne uproszczenia, bardziej przyda się do nauki programowania początkującym, niż bezmyślnego wgrywania do procesorów.
Oto listing:
//sterownik ATtiny 13A 4 tryby stałe
//Fck = 9,6MHz
//Divide by 8 ON

#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/sleep.h>

unsigned int short Ntryb=0; //numer trybu w pamięci ram
unsigned int short Lklik=0; //licznik klików w pamięci ram
unsigned int short A=1;
unsigned int short B=0;

unsigned int short EEMEM Numertrybu; //numer trybu w pamięci eeprom
unsigned int short EEMEM Licznikklikow; //licznik klików w pamięci eeprom

void przerwa(unsigned int czas) //przerwa 5ms x czas
{
while (czas > 1) //wykonuj dopóki czas >1
{
czas--; //zmniejsz czas o 1
_delay_ms(5); //czekaj 5ms
}
}

void Mryg() //mrugnięcie
{
B = OCR0B; //zapamiętaj jasność
OCR0B = 0; //zgaś LEDa
przerwa(25); //odczekaj 125ms, przekaż funkci liczbę 25
OCR0B = B; //przywróć jasność
przerwa(25); //funkcja opóźnienia 5ms, wykona się 25x
}

void Zakrestrybow() //sprawdzanie dopuszczalnego zakresu numeru trybu
{
if (Ntryb > 4) Ntryb = 1;
if (Ntryb < 1) Ntryb = 4;
eeprom_update_byte(&Numertrybu,Ntryb); //zapisz numer trybu jeśli się zmienił
}

void Jasnosci() //ustalanie poziomu jasności według trybu
{
switch(Ntryb)
{
case 1: OCR0B = 2; break; //0,8%
case 2: OCR0B = 64; break; //25%
case 3: OCR0B = 127; break; //50%
case 4: OCR0B = 255; break; //100%
}
}

void Zaswiec() //ustalenie trybu
{
Zakrestrybow(); //sprawdź zakres trybów
Jasnosci(); //ustal jasność
}

unsigned int pomiarnapiecia() //funkcja pomiaru napięcia
{
ADCSRA|= (1<<ADSC); //start konwersji
while (ADCSRA &(1<<ADSC)); //czekaj na koniec konwersji
return ADC; //zwróć wynik pomiaru
}

void Napiecie() //zabezpieczenie podnapięciowe
{
unsigned int T1=0;
ADMUX&= ~(1<<MUX1); //pomiar napięcia na dzielniku ADC 1 - skasuj MUX1, MUX0 = 1
ADMUX|= (1<<REFS0); //Vref = 1,1V - REFS0 = 1
T1 = pomiarnapiecia(); //wykonaj pomiar napięcia aku, wynik zapisz jako T1

if (T1<515) //jeśli napięcie niższe niż 3,0V - to:
{
if (OCR0B > 1) OCR0B>>=1; //jeśli PWM większy niż 1 to zmniejsz jasność o połowę
Mryg(); //mrugnij
}
}



void Strobo() //stroboskop o jasności 30%
{
eeprom_write_byte(&Licznikklikow, 255); //wykasowanie licznika klików, aby po wyjściu nie zmienić trybu
while(1)
{
OCR0B = 0; //zgaś LEDa
przerwa(25); //odczekaj 125ms
OCR0B = 85; //jasność 30%
przerwa(25); //odczekaj 125ms
Napiecie(); //sprawdź napięcie baterii
}
}

int main()
{
unsigned int T1=0; //zmienna 2 bajty, do zapisu wartości pomiaru ADC
Lklik = eeprom_read_byte(&Licznikklikow); //odczyt licznika klików

ADCSRA|= (1<<ADEN); //załączenie ADC
ADCSRA|= (1<<ADPS1) | (1<<ADPS0); //prescaler = 8

ADMUX=3; //ustaw pomiar napięcia na kondensatorze ADC3 PB3
//Vref = Vcc bo REFS0 =0 w ADMUX
T1 = pomiarnapiecia();
if (T1 > 50) Lklik++; //jeśli było napięcie, zwiększ licznik klików
if (Lklik > 5) Lklik = 0; //wyzeruj licznik klików jeśli większy od 5
eeprom_update_byte(&Licznikklikow, Lklik); //aktualizacja licznika klików jeśli się zmienił

PORTB|= (1<<PB3); //naładuj kondensator, podciągnij PB3 do VCC

TCCR0B|=(1<<CS00); //ustaw Timer0 prescaler = 1
TCCR0A|=(1<<WGM00)|(1<<COM0B1); //phase correct PWM - normalny PWM
DDRB|= (1<<PB1); //ustaw PB1 jako wyjście

Ntryb = eeprom_read_byte(&Numertrybu);
Zaswiec(); //ustaw jasność odczytanego trybu
przerwa(50); //odczekaj 250ms, czy będzie następny klik
eeprom_update_byte(&Licznikklikow, 0); //jeśli nie było klika, wyzeruj licznik klików w eprom
switch(Lklik) //wykonaj polecenie, zależnie od ilości klików
{
case 1:Ntryb++;break; //1 klik - tryb w górę
case 2:Ntryb--;break; //2 kliki - tryb w dół
case 3:Strobo();break; //3 kliki - stroboskop
}
Zaswiec(); //ustaw jasność po zmianach

while(1) //Pętla pomiarowa zabezpieczeń baterii, latarka swieci
{
Napiecie();
przerwa(1000); //odczekaj 5s
}
}

Jak widać program jest przeznaczony dla ludzi, którzy zaczynają przygodę z programowaniem, w związku z tym umieściłem sporo komentarzy przy liniach. Po kompilacji otrzymamy kod, który będzie chodził na driverkach 3 - 4 AMC, przy 8 już są problemy, ale też nie jest to "full wypas" więc trzeba się pogodzić z pewnymi ograniczeniami.
oprogramowanie ma 4 tryby zmieniane w pętlach, w górę i w dół. Dodatkowo jest strobo o jasności 30% wywoływane 3 - klikiem, oraz najprostsza ochrona ogniwa.
Życzę owocnych prób, zaczynającym przygodę z "C".

Pozdrawiam
_________________
Izali miecz godniejszy niżli topór w boju?
Piszmy po polsku, wszak jesteśmy Polakami.
Ostatnio zmieniony przez Pyra 07-02-2014, 18:52, w całości zmieniany 2 razy  
 
 
Mieciu 

Pomógł: 21 razy
Dołączył: 29 Sie 2013
Posty: 443
Skąd: Białystok
Wysłany: 07-02-2014, 18:12   

Pyra
bardzo dobry temat :-)
Powoli przymierzam się do budowy swojego sterownika 30-50W na arduino pro mini, mosfetach , czujniku prądu INA139 i czujniku temp LM35. Wczoraj zastanawialem się właśnie nad obsługą drugiego trybu.

Czy dobrze zrozumiałem że w części init dokonuję odczytu ADC z pinu podpiętego do kondensatora i jeżeli nic nie wykryję to dopiero ustawiam pin na high i lecę w pierwszym trybie?
Jeżeli natomiast coś wykryję przy starcie to lecę z drugim trybem i rowniez ustawiam pin na high?

Na jak długo starcza taka kombinacja RC 60kΩ 1µF żeby się rozładowało do 0?
Boję się że z ADC będę miał bardzo długo niezerowy odczyt, przecież jednostka to 5V/1024 czyli teoretycznie 0,00488V.

Fajnie jakbyś rozwinął temat... jakiś schemacik i fragment kodu może?
 
 
Pyra 


Pomógł: 570 razy
Dołączył: 02 Sie 2009
Posty: 8533
Skąd: Gądki
Wysłany: 07-02-2014, 18:28   

Witam
Schemat jest standardowy:

Oczywiście zamiast ATtiny13V musi być ATtiny13a. Nie wiem dlaczego, ale z wersją V, wykrywanie klika nie działa prawidłowo :-|
Kod jak widzisz umieściłem cały, nie stanowi on żadnej konkurencji dla Bociana i grega, ale ma służyć do przedstawienia idei.

Pozdrawiam
PS: jak słusznie zauważył alienth dzielnik w 105C wygląda inaczej, są to rezystory 19k1 i 4k7.
_________________
Izali miecz godniejszy niżli topór w boju?
Piszmy po polsku, wszak jesteśmy Polakami.
Ostatnio zmieniony przez Pyra 11-03-2014, 17:38, w całości zmieniany 1 raz  
 
 
ElSor 


Pomógł: 328 razy
Dołączył: 13 Wrz 2009
Posty: 4924
Skąd: Ozimek
Wysłany: 07-02-2014, 18:49   

Widzę Sławku, że podałeś ładną bazę do dalszych modyfikacji.
Tylko czy aby na pewno podany kod realizuje "void Strobo() //stroboskop o jasności wybranego trybu", bo ja widzę, że mrugać ma z mocą 30% (skonfigurowaną w programie).

PS muszę się dowartościować szukając potknięć mistrza :razz:
_________________
 
 
 
Pyra 


Pomógł: 570 razy
Dołączył: 02 Sie 2009
Posty: 8533
Skąd: Gądki
Wysłany: 07-02-2014, 18:55   

Witam
ElSor napisał/a:
PS muszę się dowartościować szukając potknięć mistrza :razz:

Raczej "miszcza" ;) W "C" dopiero raczkuję...
Masz rację, jakoś mi to umknęło, fragment przekopiowałem z innego programu i zmieniłem funkcję, a zapomniałem o komentarzu :-|
Pozdrawiam
_________________
Izali miecz godniejszy niżli topór w boju?
Piszmy po polsku, wszak jesteśmy Polakami.
 
 
Mieciu 

Pomógł: 21 razy
Dołączył: 29 Sie 2013
Posty: 443
Skąd: Białystok
Wysłany: 07-02-2014, 18:58   

Dzieki za wskazówki
Ja będę swój kod w arduino pisał, w czystym C jeszcze się nie bawiłem.
 
 
ElSor 


Pomógł: 328 razy
Dołączył: 13 Wrz 2009
Posty: 4924
Skąd: Ozimek
Wysłany: 08-02-2014, 19:40   

Właśnie robię próby driverka. Kondensator z odzysku o pojemności 3,3uF (porównuję napięcie po starcie z wartością 200 zamiast 50). Dodany beacon pod 4-klikiem, strobo ustawione, by migało z mocą trybu, z którego zostało wywołane i nieco szybsze niż fabrycznie. Cóż mogę napisać - to chyba pierwszy "gotowiec" który działa bez problemu zaraz po zaprogramowaniu i który zostanie w którejś z moich latarek na stałe, oczywiście po drobnych poprawkach pod mój gust.
Sławku, ponownie zainspirowałeś mnie do zrobienia czegoś fajnego i pokazałeś drogę, więc za to chwała i dzięki Ci :!:
_________________
 
 
 
Pyra 


Pomógł: 570 razy
Dołączył: 02 Sie 2009
Posty: 8533
Skąd: Gądki
Wysłany: 08-02-2014, 21:52   

Witam
ElSor napisał/a:
... Cóż mogę napisać - to chyba pierwszy "gotowiec" który działa bez problemu zaraz po zaprogramowaniu ...

He he, podam małą ciekawostkę, otóż są osoby, które autorytatywnie wypowiadały się, że to nie ma prawa działać (całe szczęście nie z naszego forum).
Jak uczy historia, wszyscy wiedzą, że coś jest niemożliwe, potem znajdzie się ktoś kto tego nie wie, i to zrobi ;)
Pozdrawiam
_________________
Izali miecz godniejszy niżli topór w boju?
Piszmy po polsku, wszak jesteśmy Polakami.
 
 
ElSor 


Pomógł: 328 razy
Dołączył: 13 Wrz 2009
Posty: 4924
Skąd: Ozimek
Wysłany: 08-02-2014, 22:26   

Pyra napisał/a:
Jak uczy historia, wszyscy wiedzą, że coś jest niemożliwe, potem znajdzie się ktoś kto tego nie wie, i to zrobi ;)
Przypomniałeś mi tym właśnie sytuację z pracy z minionej środy. Poszedłem na sąsiedni dział pomóc chłopakom w montażu elektryki. Stali biedni i się głowili jak to zrobić, bo na rysunku jest to tak i tak. Ja nieświadom tego mówię, że tak i tak i nie trzeba nic przerabiać. Jeszcze chwilę postali i patrzyli na mnie jak na jakiegoś guru. Jeszcze jak im dodałem, że 7 lat robię w tej firmie to w ogóle słuchali mnie jak swojego przełożonego ;-)

Co do driverka to już siedzi w Convoyu S4 :mrgreen: :mrgreen: :mrgreen:
1 klik - przełącza tryby w górę w pętli od 2-5
2 klik - przełącza tryby w dól do 1
3 klik - włącza tryb 5 lub 1 w zależności od tego w którym trybie aktualnie jestem
4 klik włącza szybkie strobo z mocą z której został wywołany o wypełnieniu +/- 40% (4 jednostki czasu świeci a przez 6 jest ciemno)
5 klik włącza "police strobe" o mocy 100%
6 klik włącza beacon o mocy 100%
Latarki używam jako rowerowej a że prawie zawsze jest w kieszeni to także jako EDC.
_________________
Ostatnio zmieniony przez ElSor 08-02-2014, 22:44, w całości zmieniany 1 raz  
 
 
 
fotorondo 

Pomógł: 42 razy
Dołączył: 01 Gru 2013
Posty: 1297
Skąd: warszawa
Wysłany: 08-02-2014, 22:42   

Z programowaniem zwykle jest tak ze zanim nie puścimy progsa po n poprawkach kodu to się nie dowiemy czy działa i czy zadziała.

po przejrzeniu kodu nie da się stwierdzić w 100% jego prawidłowości

Tak mi się wydaje.

pozdrawiam
 
 
pralat 


Pomógł: 12 razy
Dołączył: 16 Kwi 2010
Posty: 414
Skąd: Opole
Wysłany: 27-02-2014, 09:02   

Witam
Na wstępie dzięki za podzielenie się swoją wiedzą i kodem.
Chciałem uczynić kilka sugestii oszczędnościowych, jeżeli można. W ATTiny13A zawsze brakuje miejsca na dodatkowe bajery, więc może komuś przyda się parę dodatkowych bajtów.

Pyra napisał/a:
void przerwa(unsigned int czas) //przerwa 5ms x czas


funkcja wywoływana jest z minimalnym parametrem 25, co daje sleep 125 ms. Można więc przerobić ją tak:
void przerwa(uint8_t czas)
...
_delay_ms(125); //czekaj 125ms
...

Dzięki temu ograniczy się argument funkcji z dwóch bajtów do jednego. To w praktyce da o kilka bajtów mniejszy kod.

Tak samo globalne zmienne, np. unsigned int short Ntryb=0 i pozostałe. Jeżeli można, warto zamienić je na 8-bitowe (uint8_t).

Dodatkowo funkcję Jasnosci() można zrobić bez pomocy switcha:
Kod:
void Jasnosci() //ustalanie poziomu jasności według trybu
{
    static const uint8_t jasnosc[] = { 2, 64, 127, 255 };
    OCR0B = jasnosc[Ntryb - 1];
}

Oczywiście trzeba zadbać o odpowiednie wartości zmiennej Ntryb, ale widzę, że jest to robione

Po tych zmianach z początkowych 618 bajtów wynikowego kodu zrobiło się 484 (kompilowane gcc 4.5.3 z opcją -Os)

Pozdrawiam.
_________________
Mój sterownik
 
 
Pyra 


Pomógł: 570 razy
Dołączył: 02 Sie 2009
Posty: 8533
Skąd: Gądki
Wysłany: 27-02-2014, 16:04   

Witam
Dzięki za sugestie. Widzę, że przeanalizowałeś kod, i o to chodziło, aby dać działającą bazę do rozwoju.
Zdaję sobie sprawę, że kod nie jest optymalny, gdyż z wrodzonego lenistwa, .... ;)
Pozdrawiam
_________________
Izali miecz godniejszy niżli topór w boju?
Piszmy po polsku, wszak jesteśmy Polakami.
 
 
alienth 


Pomógł: 4 razy
Dołączył: 08 Paź 2012
Posty: 267
Skąd: Rzeszów
Wysłany: 11-03-2014, 13:15   

Sławku mam pytanie,
czy w tej części kodu:
Kod:
if (T1<515)    //jeśli napięcie niższe niż 3,0V


w nawiasie nie powinna być wartość 644 ?

Dla wartości 515 z wyliczeń wychodzi mi, że zmniejszasz PWM dopiero poniżej ~2,39V

Chyba, że ja coś źle liczę to proszę o poprawienie :)
_________________
Moje sterowniki:
AHE+ v1
KHE
v201 / v211
 
 
Pyra 


Pomógł: 570 razy
Dołączył: 02 Sie 2009
Posty: 8533
Skąd: Gądki
Wysłany: 11-03-2014, 17:36   

Witam
Masz rację, umieszczony schemat dotyczy driverka AK-47 i miał tylko przedstawić ogólną topologię układu. W 105C dzielnik składa się z rezystorów 1% 19k1 oraz 4k7.
Pozdrawiam
_________________
Izali miecz godniejszy niżli topór w boju?
Piszmy po polsku, wszak jesteśmy Polakami.
 
 
ElSor 


Pomógł: 328 razy
Dołączył: 13 Wrz 2009
Posty: 4924
Skąd: Ozimek
Wysłany: 12-03-2014, 03:11   

Było kilka wersji 105C. U mnie wartość ADC=518 przełącza przy ok 2,9V.
_________________
 
 
 
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Nie możesz załączać plików na tym forum
Nie możesz ściągać załączników na tym forum
Dodaj temat do Ulubionych
Wersja do druku

Skocz do:  

Powered by phpBB modified by Przemo © 2003 phpBB Group
Strona wygenerowana w 0,2 sekundy. Zapytań do SQL: 14