Szybka zmiania stanu pinów cyfrowych Atmega328

Masz problem z Arduino? Tutaj możesz szukać pomocy.
ODPOWIEDZ
zgred125
Majsterkowicz
Posty: 88
Rejestracja: 23 gru 2013, 22:39

Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: zgred125 » 28 maja 2015, 21:26

Witam

Potrzebuje za pomocą jednego polecenia zmieniać "masowo" stan pinów cyfrowych. Do tej pory korzystałem z expandera i tablicy poniżej

Kod: Zaznacz cały

byte tabela[10] =
{
  B11000000,//0
  B11111001,//1
  B10100100,//2
  B10110000,//3
  B10011001,//4
  B10010010,//5
  B10000010,//6
  B11111000,//7
  B10000000,//8
  B10010000,//9
};
Do tej pory korzystałem z niej z niej do obsługi segmentowego wyświetlacza LED za pomocą polecenia np.expander.write(tabela[0]). Jak zrealizować dokładnie to samo tyle że bez expandera. Proszę o jakąś wskazówkę bo nie bardzo wiem jak temat ugryźć

Co miesiąc do wygrania nagrody o wartości ponad 1600 zł!


stiven
Złota rączka
Posty: 1644
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: stiven » 1 cze 2015, 15:11

W jakim celu chcesz to tak zrobić?
zgred125
Majsterkowicz
Posty: 88
Rejestracja: 23 gru 2013, 22:39

Re: Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: zgred125 » 1 cze 2015, 21:16

Ponieważ przy multipleksowaniu kiedy po kolei włączam konkretne piny przy 3 okienkach jest jeszcze ok a przy czterech już wyraźnie widać migotanie. Identyczny problem miałem przy użyciu expandera. Używam mniej takiej funkcji:

Kod: Zaznacz cały


void zapal(int cyfra1, int cyfra2)
{  
      digitalWrite(D2, LOW);
    switch(cyfra1)
    {
    case 1:
      {
        digitalWrite(BB, LOW);
        digitalWrite(CC, LOW);
        break;
      }
    case 2:
      {
        digitalWrite(AA, LOW);
        digitalWrite(BB, LOW);
        digitalWrite(GG, LOW);
        digitalWrite(EE, LOW);
        digitalWrite(DD, LOW);
        break;
      }
    case 3:
      {
        digitalWrite(AA, LOW);
        digitalWrite(BB, LOW);
        digitalWrite(GG, LOW);
        digitalWrite(CC, LOW);
        digitalWrite(DD, LOW);
        break;

      }
    case 4:
      {
        digitalWrite(FF, LOW);
        digitalWrite(GG, LOW);
        digitalWrite(BB, LOW);
        digitalWrite(CC, LOW);    
        break;
      }
    case 5:
      {
        digitalWrite(AA, LOW);
        digitalWrite(FF, LOW);
        digitalWrite(GG, LOW);
        digitalWrite(CC, LOW);
        digitalWrite(DD, LOW);
        break;
      }
    case 6:
      {
        digitalWrite(AA, LOW);
        digitalWrite(FF, LOW);
        digitalWrite(GG, LOW);
        digitalWrite(EE, LOW);
        digitalWrite(DD, LOW);
        digitalWrite(CC, LOW);
        break;
      }
    }
    gas();
    digitalWrite(D3, LOW);
    switch(cyfra2)
    {
    case 1:
      {
        digitalWrite(BB, LOW);
        digitalWrite(CC, LOW);
        break;
      }
    case 2:
      {
        digitalWrite(AA, LOW);
        digitalWrite(BB, LOW);
        digitalWrite(GG, LOW);
        digitalWrite(EE, LOW);
        digitalWrite(DD, LOW);
        break;
      }
    case 3:
      {
        digitalWrite(AA, LOW);
        digitalWrite(BB, LOW);
        digitalWrite(GG, LOW);
        digitalWrite(CC, LOW);
        digitalWrite(DD, LOW);
        break;

      }
    case 4:
      {
        digitalWrite(FF, LOW);
        digitalWrite(GG, LOW);
        digitalWrite(BB, LOW);
        digitalWrite(CC, LOW);    
        break;
      }
    case 5:
      {
        digitalWrite(AA, LOW);
        digitalWrite(FF, LOW);
        digitalWrite(GG, LOW);
        digitalWrite(CC, LOW);
        digitalWrite(DD, LOW);
        break;
      }
    case 6:
      {
        digitalWrite(AA, LOW);
        digitalWrite(FF, LOW);
        digitalWrite(GG, LOW);
        digitalWrite(EE, LOW);
        digitalWrite(DD, LOW);
        digitalWrite(CC, LOW);
        break;
      }
    }
    gas();  
}
Na chwilę obecną jest to napisane tylko dla dwóch okienek. Przy expanderze moja funkcja wygląda tak i nie ma żadnego problemu z migotaniem
void zapal_jaka(int jaka, int ktory_pin)
{
switch (ktory_pin)
{
case 0:
digitalWrite(jed, LOW);
break;
case 1:
digitalWrite(dz, LOW);
break;
case 2:
digitalWrite(set, LOW);
break;
case 3:
digitalWrite(tys, LOW);
break;
}
switch (jaka)
{
case 0:
lol.write(tabela[0]);
break;
case 1:
lol.write(tabela[1]);
break;
case 2:
lol.write(tabela[2]);
break;
case 3:
lol.write(tabela[3]);
break;
case 4:
lol.write(tabela[4]);
break;
case 5:
lol.write(tabela[5]);
break;
case 6:
lol.write(tabela[6]);
break;
case 7:
lol.write(tabela[7]);
break;
case 8:
lol.write(tabela[8]);
break;
case 9:
lol.write(tabela[9]);
break;
}
zgas();
}
A czego akurat tak :-) bo inaczej nie umiem. Jeżeli jest jakiś lepszy sposób to chętnie się z nim zapoznam
stiven
Złota rączka
Posty: 1644
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: stiven » 1 cze 2015, 21:53

@Krapi
Co za różnica czy użyje expandera czy dekodera BCD?

@zgred125
Jak używasz expandera, to migotania nie masz nawet przy czterech wyświetlaczach? Chciałbyś to samo zrobić na samych pinach arduino, bez expadera, ale wtedy masz migotanie? Pytam, bo tak piszesz, że trzeba się domyślać o co chodzi. Teoretycznie nie powinno mieć znaczenia ile podłączysz wyświetlaczy przy multipleksowaniu. Kod wygląda okej, jedyne czego brakuje, to krótkich opóźnień po zapaleniu danego wyświetlacza, no chyba że masz je w funkcji gas().
stiven
Złota rączka
Posty: 1644
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: stiven » 2 cze 2015, 00:36

Cena to rzeczywiście jest duża wada ekspandera, ale jeśli chodzi o interfejs I2C, to akurat jest ogromna zaleta (stąd też wysoka cena), ponieważ do tej magistrali według specyfikacji można podłączyć do 128 urządzeń, każde musi mieć swój własny adres (arduino akurat bardzo dobrze radzi sobie z większą ilością układów podłączonych do tego interfejsu w przeciwieństwie do interfejsu SPI). Piny wykorzystane dla dekodera BCD już nie wykorzysta się do połączenia innych układów.
Krapi pisze:
jedyne czego brakuje, to krótkich opóźnień po zapaleniu danego wyświetlacza, no chyba że masz je w funkcji gas().
opóźnienie po zapaleniu się wyświetlacza właśnie sprawi migotanie (jak każdy wyświetlacz "chwilę" poświeci, to inne muszą odczekać swoje, by zapalić segmenty - nieprawdaż?)
Z tego wynika, że nie programowałeś do tej pory multipleksowania wyswietlaczy led. Jeśli nie da się żadnego opóźnienia po zapaleniu jednego wyświetlacza i przed zgaszeniem go i zapaleniem kolejnego, to jest takie "odwrotne migotanie", wyświetlacze są nieczytelne, ponieważ kod wykonuje się zbyt szybko/wyświetlacz jest zapalony za krótko. Jeśli dobrze pamiętam, to takie optymalne opóźnienie to około 10 milisekund. To można robić metodą prób i błędów, każda dodatkowa milisekunda powoduje, że wyświetlacze wyświetlają coraz wyraźniej, aż w pewnym momencie zaczyna pojawiać się migotanie.

Jeśli dobrze zrozumiałem i przy wykorzystaniu tylko jednego expandera nie było migotania, to również bez niego nie powinno być migotania jeśli nic nie zmieniło się w programie.

Krapi pisze: Przy expanderze nie może (nie powinno) być migotania, ponieważ informacje są przesyłane po I2C "w pakiecie" i to expander dekoduje pakiet otrzymanych danych i je wykonuje
Jeśli wykorzystasz tylko jeden expander (dekoder BCD), to to nie jest prawda, musiałbyś mieć ich tyle ile wyświetlaczy. Przy jednym i tak masz multipleksowanie i jest na tej samej zasadzie, a to migotanie powstaje właśnie przez zbyt duże opóźnienia między zapalaniem poszczególnych wyświetlaczy (no ale jeśli nie korzystałeś z tych wyświetlaczy, to to może być trudne do zrozumienia).
zgred125
Majsterkowicz
Posty: 88
Rejestracja: 23 gru 2013, 22:39

Re: Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: zgred125 » 2 cze 2015, 15:53

Może faktycznie trochę nie jasno. Używam jednego wyświetlacza składającego się z 4 okienek. Przy expanderze migotanie nie pojawia się wcale o ile korzystam z sposobu opisanego w moim pierwszym poście.
Chciałem uniknąć korzystania z expandera ponieważ zasilam układ z baterii a sam zupełnie nic nie robiący expander to 263 uA podczas gdy uśpiona atmega328 to około 18uA. Dodatkowo aby oszczędzać energię wyłączyłem niektóre podsystemy procka między innymi I2C :-)
Pinów cyfrowych mam wystarczająca ilość aby nie musieć podłączać expandera.

Funkcja gaś o która pojawiały się pytania:

Kod: Zaznacz cały

void gas()
{
  digitalWrite(D1,HIGH);
  digitalWrite(D2,HIGH);
  digitalWrite(D3,HIGH);
  digitalWrite(D4,HIGH);
  digitalWrite(AA,HIGH);
  digitalWrite(BB,HIGH);
  digitalWrite(CC,HIGH);
  digitalWrite(DD,HIGH);
  digitalWrite(EE,HIGH);
  digitalWrite(FF,HIGH);
  digitalWrite(GG,HIGH);
}
W kodzie nie ma ani jednego delay. W funkcji loop też nie ma nic ciekawego. Procek jest wybudzany stanem niskim wysyłą dwie cyfry do funkcji zapal w pętli powtarzanej 5000 razy i później znowu idzie spać
stiven
Złota rączka
Posty: 1644
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: stiven » 2 cze 2015, 16:14

Przed funkcją gas() daj delay(10). Możesz spróbować trochę mniej albo więcej jak coś będzie nie tak. Jak nie dasz tego delaya, to tak jak pisałem, zapalasz wyświetlacz i od razu go gasisz, tą chwilę, z 10 ms on musi się świecić. Jak miałeś expander, to prawdopodobnie expander powodował opóźnienia i dzięki temu było dobrze.
zgred125
Majsterkowicz
Posty: 88
Rejestracja: 23 gru 2013, 22:39

Re: Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: zgred125 » 2 cze 2015, 17:11

Faktycznie pomogło. Dzięki za pomoc.
zgred125
Majsterkowicz
Posty: 88
Rejestracja: 23 gru 2013, 22:39

Re: Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: zgred125 » 3 cze 2015, 10:30

Poszedłem zupełnie w złą stronę :-) byłem święcie przekonany, że migotanie bierze się z tego, że piny wyłączane i włączane są zbyt wolno i z tego to migotanie a teraz, nie dość, że nie migota to jeszcze jaśniej świeci. Troszkę jeszcze pozmieniałem w funkcjach i teraz mam jedna instrukcję switch dla wszystkich okienek wyświetlacza
stiven
Złota rączka
Posty: 1644
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: stiven » 3 cze 2015, 10:47

Nie wiem czy patrzyłeś jak jest przy innych wartościach tego opóźnienia. Czym większe opóźnienie, tym będzie jaśniej świecił. No tylko jak już będzie za duże, to zacznie być migotanie.
zgred125
Majsterkowicz
Posty: 88
Rejestracja: 23 gru 2013, 22:39

Re: Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: zgred125 » 5 cze 2015, 21:44

Sorry, że tak długo nie sprawdziłem bo czas nie pozwolił. Przy 5 jest idealnie przy 7 do akceptacji ale delikatnie widać, że coś z cyferkami jest nie tak a przy 10 już ewidentnie migocze
stiven
Złota rączka
Posty: 1644
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: stiven » 5 cze 2015, 21:58

No to w porządku, myślałem, że wpisałeś 10 ms i było dobrze (a mogłoby być lepiej). Ja jakiś czas temu zrobiłem sobie termometr pokazujący temperaturę na wyświetlaczach led. Kod mi zginął, wydawało mi się, że opóźnienia miałem na kilkanaście milisekund. Może to zależy jeszcze od czegoś, ale raczej się pomyliłem.
zgred125
Majsterkowicz
Posty: 88
Rejestracja: 23 gru 2013, 22:39

Re: Szybka zmiania stanu pinów cyfrowych Atmega328

Post autor: zgred125 » 6 cze 2015, 00:32

Nie chciał bym walnąć babola ale wydaje mi się, że ludzkie oko gubi się przy 25 klatkach na sekundę przy ledach potrzebne będzie pewnie więcej powiedzmy 50 klatek. Cyferek jest 4 więc 200Hz powinno wystarczyć czyli 5 ms
ODPOWIEDZ

Strony partnerskie: