Elektroda.pl
Elektroda.pl
X
Elektroda.pl
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

74HC595 - inżynieria wsteczna

06 Maj 2017 17:30 1434 17
  • Poziom 10  
    Witajcie.
    Długo kopałem w sieci i nie znalazłem niczego przydatnego.

    Mam komputer sterujący od bieżni z uszkodzonym procesorem. Procek wywaliłem i została mi się tablica z ledami i wyświetlaczami 7 segm. Próbuję ją obsłużyć z poziomu arduino. Udało mi się zaświecić wszystkie ledy, ale nie podobał mi się efekt.

    Układ składa się z 7 układów 74HC595 i 8 tranzystorów.
    Code:

    g_registerArray [0] = B00000001;
    g_registerArray [1] = 0; //incline 1 znak
    g_registerArray [2] = 0; // distance 1 znak
    g_registerArray [3] = 0; // [program / pulse 1 znak
    g_registerArray [4] = 0; // matryca pierwsza kolumna
    g_registerArray [5] = 0; // postep programu 1 piec LED
    g_registerArray [6] = 0; // postep programu 3 piec LED
    g_registerArray [7] = 0; //??
    sendSerialData (8, g_registerArray);
    delay(1);

    g_registerArray [1] = B00000010;
    g_registerArray [2] = 0; //incline 2 znak
    g_registerArray [3] = 0; // distance 2 znak
    g_registerArray [4] = 0; // [program / pulse 2 znak
    g_registerArray [5] = 0; // matryca druga kolumna
    g_registerArray [6] = 0; // postep programu 2 piec LED
    g_registerArray [7] = 0; // postep programu 6 piec LED
    sendSerialData (8, g_registerArray);
    delay(1);
    ...

    g_registerArray [1] = B01000000;
    g_registerArray [2] = 0;
    g_registerArray [3] = 0;
    g_registerArray [4] = 0;
    g_registerArray [5] = 0;
    g_registerArray [6] = 0;
    g_registerArray [7] = 0;
    sendSerialData (8, g_registerArray);
    delay(1);


    Ten kod umożliwia zapalenie wszystkich LED na tablicy. Niestety przez krótki czas świecenia świecą słabo. Po wydłużeniu czasu wyświetlania pojawia się migotanie.

    Próbowałem innych metod, ale żadna nie umożliwia zapalenie wszystkich punktów. Nie mam pojęcia jak użyć shiftOut w tym przypadku.
    Proszę o pomoc.
  • Poziom 38  
    Tego typu wyświetlacz zawsze jest multipleksowany. Oznacza to, że wprowadza się do rejestru przesuwnego całą linię kolumn 7szt.x8bit(HC595), następnie ją zatrzaskuje i wysterowuje tranzystor rzędu na określony czas, regulacja jasności. Linia sobie świeci a tym czasem procesor ma czas poskładać w RAM następną linię kolumn dokonując translacji znaków zapisanych w tablicy ROM. Ma na to 40ms/8 rzędów= 5ms/rząd by uniknąć migotania. HC595 nie ma takiej obciążalności by można było wysterować wszystkie diody LED dla danej kolumny czyli zapalić wszystkie diody na wyświetlaczu na stałe.
  • Poziom 10  
    RitterX napisał:
    Tego typu wyświetlacz zawsze jest multipleksowany. Oznacza to, że wprowadza się do rejestru przesuwnego całą linię kolumn 7szt.x8bit(HC595), następnie ją zatrzaskuje i wysterowuje tranzystor rzędu na określony czas, regulacja jasności. Linia sobie świeci a tym czasem procesor ma czas poskładać w RAM następną linię kolumn dokonując translacji znaków zapisanych w tablicy ROM. Ma na to 40ms/8 rzędów= 5ms/rząd by uniknąć migotania. HC595 nie ma takiej obciążalności by można było wysterować wszystkie diody LED dla danej kolumny czyli zapalić wszystkie diody na wyświetlaczu na stałe.


    Bez problemu mogę wysterować dowolny tranzystor podając w pierwszej linii jego adres.
    Code:
    g_registerArray [0] = B00000001;

    W następnych bajtach po kolei podaję informację do poszczególnych segmentów. Wszystko jest cacy do momentu gdy wyślę dane po kolei w paczkach na wszystkie segmenty. Wtedy świeci się tylko ostatni. Spróbowałem w pętli to podać i każdy tranzystor przez delay(1) przytrzymać, ale
    wtedy bardzo słabo świecą.
    Paczki wysyłam poniższą procedurą:
    Code:

    void sendSerialData (
    byte registerCount,
    byte *pValueArray)
    {
    digitalWrite (g_pinCommLatch, LOW);
    for (byte reg = registerCount; reg > 0; reg--)
    {
    byte value = pValueArray [reg - 1];

    for (byte bitMask = 128; bitMask > 0; bitMask >>= 1)
    {
    digitalWrite (g_pinClock, LOW);
    digitalWrite (g_pinData, value & bitMask ? HIGH : LOW);
    digitalWrite (g_pinClock, HIGH);
    }
    }
    digitalWrite (g_pinCommLatch, HIGH);
    }
  • Specjalista elektronik
    Pytanie, co masz na wyjściach 74HC595. Powinieneś mieć te 56 bitów, które wysyłasz. Hm... chyba nie napisałeś, jakie są wymiary matrycy (ile LED-ów na ile).

    W tym kodzie nie widzę włączania/wyłączania tranzystorów - a powinno być tak, że przed "digitalWrite (g_pinCommLatch, HIGH);" wyłączasz tranzystor, a po włączasz następny, odpowiadający rzędowi, dla którego właśnie wysłałeś dane. Poza tym: registerCount ma być stałe, równe ilości 74HC595 - zawsze trzeba wysyłać tyle bitów, ile się mieści do wszystkich 74HC595.

    Może, skoro nazwałeś procedurę 'sendSerialData', wywal z niej pisanie na pinCommLatch? Nie ma znaczenia, kiedy wpisujesz tam LOW - tylko kiedy wpisujesz HIGH, i możesz te operacje wykonywać po wywołaniu tej procedury.

    To powinno działać tak, że włączony jest 1 tranzystor (wybierający rząd) i te wyjścia 74HC595, którym odpowiadają LED-y do zaświecenia w tym rzędzie. Czekasz np. 1ms, potem ładujesz do 74HC595 dane dla następnego rzędu, wyłączasz tamten tranzystor, każesz przepisać dane, włączasz następny tranzystor.
  • Poziom 10  
    74HC595 - inżynieria wsteczna
    19 wyświetlaczy 8 segm.
    8x8 matryca
    10 x 5 wskaźnik postępu
    2 x 16 słupki led

    To daje 298 punktów.
    Przyznam z bólem że trochę trudna ta logika. Myślałem że podanie w pierwszym bajcie "1, 2, 4, 8, 16, 32, 64, 128" spowoduje wybranie konkretnego wiersza... Wydawało mi się że tak postępując odnajduje który bajt odpowiada za konkretny segment. Powinienem więc przerobić procedurę sendSerialData:
    Code:

    void sendSerialData (byte registerCount, byte *pValueArray, byte Col)
    {
    for (byte reg = registerCount; reg > 0; reg--)
    {
    byte value = pValueArray [reg - 1];

    for (byte bitMask = 128; bitMask > 0; bitMask >>= 1)
    {
    digitalWrite (g_pinClock, LOW);
    digitalWrite (g_pinData, value & bitMask ? HIGH : LOW);
    digitalWrite (g_pinClock, HIGH);
    }
    }
    digitalWrite (g_pinClock, LOW);
    digitalWrite (g_pinData, Col & bitMask ? HIGH : LOW);
    digitalWrite (g_pinClock, HIGH);
    digitalWrite (g_pinCommLatch, HIGH);
    }

    g_registerArray [0] = 0;
    g_registerArray [1] = 0; //incline 1 znak
    g_registerArray [2] = 0; // distance 1 znak
    g_registerArray [3] = 0; // [program / pulse 1 znak
    g_registerArray [4] = 0; // matryca pierwsza kolumna
    g_registerArray [5] = 0; // postep programu 1 piec LED
    g_registerArray [6] = 0; // postep programu 3 piec LED
    g_registerArray [7] = 0; //??

    sendSerialData (8, g_registerArray, 1);
  • Specjalista elektronik
    To może trzeba poszukać, jak są połączone te 74HC595 - wejścia pewnie w dość standardowy sposób, ale z oglądaniem wyjść będzie nieco zachodu.

    7 sztuk 74HC595 pozwala (przy założeniu, że do 8 wyjść są podłączone tranzystory do multipleksowania) na sterowanie 8x6x8=384 punktów, więc nie wszystkie są wykorzystane.

    Trzeba najpierw ustalić, które wyjścia są do tranzystorów. Potem włączyć jeden tranzystor i włączać pojedynczo każde z pozostałych wyjść np. na 1 sekundę, i obserwować.

    Ostatni wysłany bajt idzie do pierwszego 74HC595 (w kolejności, w jakiej są połączone).
  • Poziom 38  
    Bez nawet zgrubnego okreslenia sposobu połączenia niewiele wskórasz. Jak jest sterowany sygnał zatrzaskiwania STCP i MR (master reset). Zdarza się, że na samym końcu w ostatnim rejestrze przesuwnym wyjście Q7 czyli, to które służy do połączenia z następnym zestawem rejestrów w kolejnym HC595 jest podłączone do MR. Wtedy wysłanie kolejnego bitu kasuje całą linię i można wysłać kolejny inkrementowny rząd kolumn bez migania segmentami. Tak się robi w układach bez zatrzaskiwania danych a nie wiadomo czy pierwotnie nie było to zbudowane np. na HC164 a w kolejnej wersji jedynie przerobione PCB?
  • Specjalista elektronik
    :arrow: Zdarza się ... - To są konkretne układy, i połączone w konkretny sposób, więc albo coś jest, albo nie ma - i trzeba to sprawdzić oglądając połączenia, a nie snuć hipotezy bez podstaw do nich. Sensowne jest połączenie szeregowe, pozwala sterować wszystko trzema sygnałami. Czy przy połączeniu Q7 z MR następnego widzisz możliwość wpisania wszystkich danych?

    A 74HC595 działa tak, że potrzebne jest zbocze sygnału ładowania szeregowego, żeby wpisać bit danych (a rejestry można łączyć szeregowo i kolejno wpisać dane do wszystkich), i zbocze sygnału przepisywania, żeby przepisać aktualne dane (bo po załadowaniu każdego bitu one się przesuwają) na wyjścia. Jako HC164 da się go użyć tylko łącząc te dwa wejścia, a z oznaczeń w programie wynika, że one są oddzielne.
  • Poziom 10  
    Trochę zajęło mi przekopanie się przez druk dwustronny. Otóż pierwszy 595 steruje 8 tranzystorami. Gdy szukałem który bajt powoduje zaświecenie konkretnych LED odkryłem że wystarczy w paczce podać na samym początku który tranzystor chcę wysterować. Oczywiście mogłem wszystkie naraz wysterować :). Znacznie gorzej jest gdy chcę obsłużyć całość. Udało się gdy w po każdej paczce odczekałem milisekundę. Większy czas powoduje wyraźne migotanie. Mimo to efekt jest niezadowalający, gdyż świecą dużo słabiej niż w oryginale.
    Procesor który usunąłem jest jakimś dedykowanym układem do takich właśnie tablic, ma dwa lub trzy wejścia liczące, kilka wyjść, obsługę klawiatury matrycowej i sterowanie LED. Jest złącze do programowania. Niestety procek na obu tablicach jest trupem.
    Mogę przedzwonić płytkę miernikiem raz jeszcze jeśli mamy szukać czegoś konkretnego.
  • Specjalista elektronik
    Sprawdź, którymi pinami 595 są ze sobą połączone. Najbardziej sensowne są połączenia: (sygnał SCK) pinów 11 (SCK) wszystkich układów, (sygnał RCK) pinów 12 (RCK) wszystkich, pinów 10 (-SCLR) wszystkich do '1', pinów 13 (-G) wszystkich do '0', pinu 14 (SER) do pinu 9 (QH') poprzedniego układu (a SER pierwszego do sygnału SER), pinów 15 i 1-7 (QA-QH) do LED-ów; no i oczywiście zasilanie i masa (piny 8 i 16) powinny być sensownie połączone.

    W takim połączeniu masz 3 sygnały wejściowe: SER=g_pinData, SCK=g_pinClock, RCK=g_pinCommLatch. Dla procedury sendSerialData pierwszy bajt ma mieć jeden bit ustawiony i określa, który tranzystor ma być włączony (zakładając, że tranzystory są podłączone do pierwszego 595), i pewnie 6 kolejnych bajtów ma podawać stany na wyjściach pozostałych 595.

    Jeśli tylko na jednym z wyjść tych pewnie 6-ciu 595 ma być '1', i ma być włączony 1 tranzystor, to trzeba w bajcie 0 wpisać 1 bit '1', resztę 0, i w jednym z pozostałych 6-ciu bajtów 1 bit ustawić, a całą resztę wyzerować. To daje 384 możliwe kombinacje... no, może jeszcze wypróbować same '0', czyli 385 kombinacji.
  • Poziom 10  
    Całą tablicę udało mi się poprawnie wysterować.
    Mam jeszcze jeden problem. Nie chcę zakładać osobnego tematu, bo szkoda zaśmiecać forum. Chodzi mi o sygnał zwrotny impulsatora prędkości. Musiałem ominąć układy na płytce wyświetlacza, gdyż z niewiadomych powodów nie ma jednej z mas. Dokładniej masa z układu zasilania, która jest masą wspólną z arduino, nie jest połączona z masą układu inwerterów. (Być może sprawiły to gryzonie).
    Sygnał z impulsatora podpiąłem pod pin arduino mostkując konsensatorem 10n z masą. Impulsy generują przerwanie. Niestety zauważyłem że kilka procent impulsów jest gubionych. Jak prawidłowo likwidować drgania styków w takim przypadku?
  • Poziom 10  
    _jta_ napisał:
    Czy problem wciąż jest aktualny? Nie bardzo rozumiem: drgania styków powodują gubienie impulsów? Spodziewałbym się, że wygenerują dodatkowe.


    Tak problem jest aktualny. Być może wszystko liczy się dobrze.
    Więc tak: zmierzyłem dokładnie ile impulsów przypada na metr bieżący bieżni. Wyliczam wszystko w programie i efekt jest taki że prędkość pływa. Sprawdzałem co sekundę ilość zliczonych impulsów i rzeczywiście to wygląda jakby co jakiś czas impuls uciekał. Nie mam roweru z licznikiem bo sprawdziłbym czy czasem nie jest spowodowane nierówną pracą silnika (np taśma w jakimś miejscu stawia większy opór.
    Dodałem kondensator, bo w oryginalnym układzie impulsy wchodziły na inwertery. Mi nie udało się odczytać impulsów po przejściu przez ten układ, wpiąłem się więc bezpośrednio w arduino.
  • Poziom 10  
    Robiłem eksperyment i w kodzie zostawiłem tylko liczenie impulsów i sterowanie silnikiem.
    Impulsy wchodzą generują przerwanie w mikrokontrolerze, w obsłudze przerwania następuje liczenie.
    Czujnik to kontrakton, bo Halla wymagałby zasilania. Może jednak coś w kodzie:

    attachInterrupt(digitalPinToInterrupt(PIN_PREDKOSC), onStep, FALLING);

    void onStep()
    {
    impuls_sensor++;
    }

    Możliwe że pętla główna nie pozwoliłaby na obsługę przerwania?