Hlavní

Málo vstupů na arduinu? Dva a více 74hc165 za sebou #2

Zdravím vás, kutilové a výzkumníci.

Dnes vám předkládám svoji verzi rozšiřování digitálních vstupů pro Arduino Nano.

Použil jsem hojně rozšířený obvod 74hc165. Na internetu se dočtete v mnoha diskusích, jaké jsou problémy s časováním, použití knihoven a podobně, proto zde předkládám použití bez knihoven a jednoduchý příklad.

Schéma zapojení mého modulu:

Jak můžete vidět na obrázku níže, rozmístění vstupů je takové, aby šly připojit moduly, které potřebují „servo“ napájení: zem-plus-signál (8 vstupů), přepínače pro nastavování parametrů programu (4 vstupy) a vstupy pro spínače proti zemi (gnd) s pomocnými tlačítky, když si třeba potřebujete ověřit nějakou funkčnost při ladění (4 vstupy).

Moduly se dají řetězit, limitem je jen paměť použitého procesoru/arduina. Počet čipů nastavujete na začátku programu nebo si můžete nastavit i dynamické rozšiřování pomocí Jumperů či DipSwitchů – přepínačů.

Možná vás překvapil druhý konektor na vstup – ten je jen kvůli tomu, kdybyste potřebovali připojit kabeláž z druhé strany. Pokud byste použili oba najednou, nic neshoří – je použit ochranný odpor, ale nebude to fungovat správně. Řekl bych prapodivně, někdy vyzkouším 🙂

Velikost desky je 60x30mm, v případě zájmu se můžeme domluvit 😉

/* název souboru: shift_in_165x2_test3
 * použit obvod: SN74HC165N
 * inspirace: https://dduino.blogspot.com/2012/04/arduino-74hc165-psio-shift-regsiter.html
 * 
 * upravil a odladil: L. Vohralík, MerkurRobot.cz, (c)2025
 *
*/

// Počet zapojených posuvných registrů 74HC165
#define NUMBER_OF_SHIFT_CHIPS 6

// Zpoždění v mikrosekundách pro signály
#define PULSE_WIDTH_USEC 5

// Interval mezi čteními v milisekundách
#define CEKEJ 100

// Připojení pinů k Arduinu
int dataPin  = 2; // Výstup Q7 z 74HC165
int ploadPin = 3; // Paralelní načtení (LOAD)
int clockPin = 4; // Hodinový vstup (CLOCK)

// Pole pro uchování hodnot z registrů
byte vstupy[NUMBER_OF_SHIFT_CHIPS];

// Funkce pro načtení hodnot z řetězce 74HC165
void read_shift_regs()
{
    byte bitVal;
    byte bytesVal = 0;

    // Spustit paralelní načtení – zachycení stavu vstupů
    digitalWrite(ploadPin, LOW);
    delayMicroseconds(PULSE_WIDTH_USEC);
    digitalWrite(ploadPin, HIGH);

    // Postupné načítání jednotlivých bajtů z registrů
    for (int j = 0; j < NUMBER_OF_SHIFT_CHIPS; j++) {
        bytesVal = 0;
        for (int i = 0; i < 8; i++) {
            bitVal = digitalRead(dataPin);
            bytesVal |= (bitVal << (7 - i)); // Uložení bitu do bajtu (MSB první)

            // Taktování hodin – přechod na další bit
            digitalWrite(clockPin, HIGH);
            delayMicroseconds(PULSE_WIDTH_USEC);
            digitalWrite(clockPin, LOW);
        }
        vstupy[j] = bytesVal; // Uložení načteného bajtu do pole
    }
}

// Výpis hodnot všech vstupů do Serial monitoru
void display_pin_values()
{
    for (int j = 0; j < NUMBER_OF_SHIFT_CHIPS; j++) {
        for (int i = 0; i < 8; i++) {
            if ((vstupy[j] >> i) & 1)
                Serial.print("|");  // Logická 1
            else
                Serial.print("-");  // Logická 0
        }
        Serial.print(".");
    }
    Serial.println();
}

// Funkce vrátí hodnotu vstupu podle pořadí od procesoru (0 = nejbližší bit od MCU)
bool vstup(int cislo_vstupu)
{
    if (cislo_vstupu < 0 || cislo_vstupu >= NUMBER_OF_SHIFT_CHIPS * 8)
        return false; // mimo rozsah, bezpečnostní kontrola

    int index = cislo_vstupu / 8;           // který čip (bajt)
    int bit_pozice = cislo_vstupu % 8;      // který bit v bajtu (0 = LSB, 7 = MSB)

    return (vstupy[index] >> bit_pozice) & 1;
}

//     setup ****************************************************************************
void setup()
{
    Serial.begin(115200);

    pinMode(ploadPin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, INPUT);

    digitalWrite(clockPin, LOW);
    digitalWrite(ploadPin, HIGH);

    display_pin_values(); // První výpis hodnot po startu
}

//     loop ****************************************************************************
void loop()
{
    read_shift_regs();     // Načtení hodnot ze všech registrů
    display_pin_values();  // Výpis na sériový monitor
    if (vstup(0)) {
        Serial.print("Vstup 0 je HIGH");
    } else {
        Serial.print("Vstup 0 je LOW");
    }
    delay(CEKEJ);
}

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *