• 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
Wyswietlacz 7-segmentowy
#1
Witam, mam problem z kodem obsługującym dwa 7-segmentowe wyświetlacze ze wspólną anodą.
A mianowicie, aktualnie program liczy od 0 do 9999. do 99 jest wszystko w porządku, ale z przejściem na 3 cyfrę coś się knoci, dalej liczy od 100 w górę, ale na pierwszej cyfrze jest liczba setek. Oto kod:
Kod:
int digits[10] = {0b11000000, 0b11111001, 0b10100100, 0b10110000, 0b10011001, 0b10010010, 0b10000010, 0b11111000, 0b10000000, 0b10010000};
//zdefiniowanie wszystkich liczb na wyswietlaczu 7 segmentowym (w kolejnosci od 0 do 9) stany sa odwrocone, 0 jest gdy swieci, 1 gdy nie swieci.
void setup() {
 DDRA = 0xFF; //zdefiniowanie wszystkich portow A jako wyjscia
 PORTA = 0xFF; //wszystkie wyjscia portu A maja stan wysoki, wyswietlacz ze wspolna anoda
 pinMode(2, OUTPUT); // pierwsza od prawej cyfra
 pinMode(3, OUTPUT); // druga od prawej cyfra
 pinMode(4, OUTPUT); // trzecia...
 pinMode(5, OUTPUT); // czwarta ..
}

void disp(char *c) {
 int _time = millis();
 char tmp[2];
 while(millis()-_time < 100) { //jedna cyfra ma byc pokazywana przez 100 milisec
   for (int j = 0; j < strlen(c); j++) { //petla dla kazdej cyfry
    digitalWrite(j+2, HIGH); //zapalenie odpowiedniej cyfry. jest +2 bo cyfry zaczynaja sie od drugiego pinu
     tmp[0] = c[j];
     tmp[1] = '\0'; //zakonczenie tablicy
     delay(1); //niewiem dlaczego, ale bez tego delaya nie chce dzialac :/ Pokazuja sie razem te same cyfry na 2 pierwszych cyfrach(od prawej)
     PORTA = digits[atoi(tmp)]; // ustawianie portu A do konkretnej liczby
    digitalWrite(j+2, LOW);
   }
 }
}

void invert(char *c) { //funkcja odwracajaca tablice znakow np z takiej postaci {5, 1, 2, 7} do {7, 2, 1, 5}. Ta funkcja jest dlatego, iz cyfry sa wyrywnane do prawej
 char temp[5];
 for(int i = 0; i < 5; i++) {
   temp[i] = c[4-i];
 }
   for(int i = 0; i < 5; i++) {
   c[i]=temp[i];
 }
}

void loop() {
 char _buffer [5];
 for(int i = 0; i < 9999; i++) {
     char _buffer [5];
     itoa(i, _buffer, 10); //konwersia liczby (int) do tablicy znakow (char)
     invert(_buffer); //odwrocenie tablicy znakow (char)
     disp(_buffer); //funkcja wyswietlajaca liczbe na wyswietlaczu
 }
}

jakby ktoś wolał na Pastebinie:
Kod:
https://pastebin.com/wACF88Ub

Dodam że moja przygoda z arduino nie jest zbyt długa  Big Grin. Proszę kogoś doświadczonego o pomoc, w wyjaśnieniu owego błędu. Pozdrawiam
 
Odpowiedź
#2
Zacznij od poprawnego napisania obsługi wyświetlacza na przerwaniach od timera.
 
Odpowiedź
#3
(30-09-2018, 21:48)es2 napisał(a): Zacznij od poprawnego napisania obsługi wyświetlacza na przerwaniach od timera.

Hmmm ok. W najbliższy weekend jak bd miał trochę czasu spróbuje coś ogarnąć. Chodzi o coś takiego? https://www.instructables.com/id/Create-...n-Arduino/
Czy coś z timerem0. Widziałem gdzieś jakieś przykłady ale nie moge tego zrozumieć, poratuje ktoś?
(byłbym wdzięczny za jakiś najprostszy przykład implementacji Big Grin)
 
Odpowiedź
#4
W Arduino tak tego się nie robi, bierze się scalak 74hc595, lub kilka, znajduje bibliotekę, podłącza zgodnie ze schematem i już. Na tym forum na pewno było bo wklejałem kiedyś kod. Chyba nikt jeszcze nie wpadł na tak pokręcony sposób. W ogóle w UNO nie ma tego portu, to jest jakaś MEGA? Załączaj kod i schematy, zdjęcia. No i polecenia sugerują, że coś wiesz o C i AVR. Może się zdecyduj, której opcji używasz. No i to banglowanie między stringami a liczbami - majstersztyk. W tablicy masz już liczby, jak chcesz wiedzieć jaka liczba jest na poszczególnym miejscu to się dzieli przez np. 100 / lub bierze resztę z dzielenia % modulo.
Chcesz robić w C (w Arduino też skompiluje i wgra) to google AVR multipleksowanie led - znajdziesz tyle że przez miesiąc pewnie tu nie zajrzysz http://diycenter.acid19.linuxpl.com/read...icle_id=19. A dla Arduino jest kurs, jest to jedna z lekcji, polecam całość: https://forbot.pl/blog/kurs-arduino-ii-w...we-id18413.
W Twoim programie źle działa funkcja odwracająca, wyświetl sobie w normalnej kolejności. Robisz coś ze znakiem końca stringa w tabeli? Jak był na czwartej pozycji to gdzie jest po odwróceniu? Działa puki jest symetrycznie. To nie jedyny błąd w tej funkcji. Wydrukuj sobie na serial wartości tablic przed i po odwróceniu.
Z liczbami nie byłoby tego problemu, w ogóle tablica tak jakoś byłaby mało potrzebna.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#5
(02-10-2018, 01:23)kaczakat napisał(a): W Arduino tak tego się nie robi, bierze się scalak 74hc595, lub kilka

Jeśli już kombinować z zewnętrznymi sterownikami, to użyć typowego sterownika LED a nie rzeźbić na rejestrach przesuwnych.
Zalety sterownika:
- 2 (I2C) a nie 3 (CK, DATA, LATCH) linie sterujące. W AVR, gdy do sterowania rejestrów użyje się SPI, to zajmujemy 4 linie.
- nie wymaga rezystorów ograniczających prąd (4 LED 7-SEG to 4*8 = 24 rezystory)
- sprzętowa regulacja jasności wyświetlacza
- łatwe, całkowicie sprzętowe sterowanie (na przerwaniach). W AVR, użycie sprzętowego SPI i przerwań, nie jest proste, ponieważ trzeba wygenerować sygnał LATCH. Nie można tego zrobić zaraz po zapisaniu w przerwaniu bajtu do SPI, bo LATCH nastąpi w trakcie transmisji danych. Trzeba więc poczekać na koniec transmisji.

Te kilka zalet przekona każdą rozsądną osobę do używania dedykowanych sterowników a nie protez w postaci rejestrów.
 
Odpowiedź
#6
Hmmmm ok. Czyli mogę to zrobić na przerwaniach od timera0? Czy w Arduino raczej nie. Chciałbym coś się nauczyć, a mam taki pomysł żeby w pętli loop tylko ustawiać np w jakiejś zmiennej liczbę do wyświetlacza.
A funkcja obsługująca przerwanie wyświetlała by te liczby np jak mam 4 cyfry dostępne to za każdym przerwaniem flaga zawierałaby liczbę, która jest aktualnie wyświetlana np liczba to 4567 to flaga najpierw ma 1, bo 1 cyfra funkcja zmienia stan portu czyli 1 cyfrę na 4 i zmiana flagi na 2 i koniec funkcji przerwania. I tak dla każdej cyfry, jak flaga bd miała 5 to bd na początku funkcji przerwania if który sprawdza to i jak jest 5 zmienia na 1. Częstotliwość tego timera0 może z 500 Hz ? Co wy o tym myślicie? Dobry pomysł czy znowu jakiś taki zawiły, zagmatwany?
 
Odpowiedź
#7
Czy w Arduino na AVR można podpiąć się pod przerwanie timera 0? Można!
Arduino na AVR do swoich celów używa przerwania od przepełnienia, tego pewnie nie ruszysz ale ją jeszcze przerwania od porównania. Nie można zmienić częstotliwości tych przerwań (około 1ms) bo zmienisz czas działania millis ale w tym przypadku ok 1ms będzie ok.

Co do dalszej treści pytania, to nie wymyślaj koła na nowo tylko poczytaj o multipleksowaniu i zrealizuj tak jak to się powinno robić czyli wyświetlasz zawartość jakiegoś bufora odwzorowującego stan segmentów A...H poszczególnych wyświetlaczy. Wszelkie przeliczanie, konwersje, dekodowanie realizujesz w programie głównym ewentualnie w innym przerwaniu np10 razy na sekundę. Takie przerwanie powinno mieć niższy priorytet niż przerwanie od timera0, jak to zrealizować gdy AVR nie oferuje wielopoziomowego systemu IRQ? Szukaj pod hasłem "INTERRUPT" i "ISR_NO_BLOCK".

W przerwaniu od timera0 możesz jedynie dodać blink. Jest to wygodniejsze w użyciu niż zmiana zawartości bufora w pętli głównej.
 
Odpowiedź
#8
Eh ok. Poczytam jeszcze Tongue
 
Odpowiedź
#9
Co do multoplexowania to myślę że tak mam aktualnie, wiem o co w tym chodzi. Załącze później schemat, jak to jest podlaczone.
 
Odpowiedź
#10
Podłączone może masz dobrze ale program świadczy o tym, że o multipleksowaniu nie masz pojęcia.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości