Programmierproblem mit Schieberegister SN74HC165

Hallo Zusammen
Nun ich bin ganz neu in die Matherie Arduino eingestiegen und versuche mir nun einiges davon selbst beizubringen. Daher beschränkt sich mein Fachwissen auf die niedrigsten Grundlagen.
Ich habe folgendes Problem:
Ich möchte mir selber einen Gamecontroller für den PC bauen. Resp. es soll eine Sidepanel erweiterung zu meinem Lenkrad werden. So… übermütig wie ich bin soll der Controller mehr Taster bekommen, als mein Leonardo digitale Pins hat. daher habe ich mir ein paar Schieberegister SN74HC165 bestellt. Nun komme ich allerdings beim Programm nicht weiter. Taster auslesen funktioniert. Damit ich aber diese Werte der Taster an den PC weitergeben kann, habe ich mir die Joystick library draf gemacht. mit dem Befehl joystick.setButton kann ich nun die PinValues welche ich aus den Schieberegister auslese an den Gamecontroller auf dem PC weitergeben. Allerdings passiert nun folgendes:
wenn ich einen Taster drücke sendet er mir das signal auf alle aktiven virtuellen Taster auf dem Gamecontroller. Heisst am Bildschirm Leuchten alle “Taster”. Wie kann ich nun das Signal von einem Taster an einen definierten “Taster” am bildschirm definieren, damit da nur auf einem das Signal ankommt und nicht auf allen?
Kann mir da jemand weiterhelfen. oder mache ich da sogar Grundlegend was falsch?

Shift_Reg_Test_005.ino (3.88 KB)

Hi

Deine .ino als Anhang ist schon Mal nicht der schlechteste Versuch - direkt hier im Forum in Code-Tags wäre Das noch um Größenordnungen besser.

Kannst Du mit der Lib Deine zusätzlichen Taster zum Rechner übertragen?
Ich meine NICHT, ob Du bei Druck auf Taster 39 irgend etwas zum PC bekommst, sondern, ob Du vom Arduino die einzelnen Taster zum Rechner schicken kannst.

Im Endeffekt erst Mal eine Schleife, Die in jedem Durchlauf EINEN der Taster zum PC als gedrückt sendet - von mir aus in der nächsten Runde als 'wieder los gelassen' - kenne Da die Lib nicht.

Wenn DAS funktioniert, hast Du gute Chancen, daß Du mehrere Taster unabhängig voneinander vom PC erkennen kannst.

... warum eigentlich immer mit dem Mars-Roboter anfangen?? Erst Mal die grundlegenden 'Verbindungen' einzeln durchspielen.
Wenn das 'Taste erkennen' im Test-Sketch schon nciht funktioniert, brauche ich Das beim Mars-Roboter gar nicht erst einbinden - über die Masse an Problemen werde ich SO nie Herr!!

MfG

Hy und besten Dank für deine rasche Antwort.
Das mit dem Mars- Roboter ist leider so eine Sache die bei mir häufiger vorkommt… Sorry

nun ich habe evt. nicht die richtigen Worte gefunden.

Also wenn ich das richtig verstehe ist in der Variable “pinValues” der zustand des Schalters gespeichert.
Wenn ich einen Taster Drücke zeigt mir der Serielle Monitor folgendes an:

Pin States:
Pin-0: HIGH
Pin-1: LOW
Pin-2: LOW
Pin-3: LOW
Pin-4: LOW
Pin-5: LOW
Pin-6: LOW
Pin-7: LOW
Pin-8: LOW
Pin-9: LOW
Pin-10: LOW
Pin-11: LOW
Pin-12: LOW
Pin-13: LOW
Pin-14: LOW
Pin-15: LOW

Dies sind ja die 16 Eingänge von den beiden Schieberegistern. Da ist zu sehen, dass Pin-0 High ist.
Nun zu meiner Frage wie kann ich diesen “Pin-0” einem definierten “virtuellen Taster” auf der Gamecontroller-Schaltfläche zuweisen?
Ich weiss, dass ich mit joystick.setButton(0,pinValues); ja jetzt den Wert an den “virtuellen Taster” 1 ausgebe.
Wenn ich nun joystick.setButton(1,pinValues) und joystick.setButton(2,pinValues) auch auskomentiere sendet er mir an alle drei den selben zustand. Ich will ja aber Pin-0 nur auf einem der drei “virtuellen Taster” haben.

Im Anhang noch ein Bild der Gamecontroller Oberfläche…

MFG

Snip_Gsamecont_001.PNG

Hi

Da verstehe ich Dich wohl nicht ganz - wenn Du allen drei virtuellen Tastern den gleichen Wert zuweist (hier 'pinValues') - dann ERWARTE ich, daß alle Taster den gleichen Wert haben.

Was bekommst Du, wenn Du

joystick.setButton(1,LOW);
joystick.setButton(2,HIGH);
joystick.setButton(3,LOW);
joystick.setButton(4,HIGH);

ausführst?

Wenn hier jetzt die Punkte für 2 und 4 hell angezeigt werden, dann musst Du 'nur' für die entsprechenden virtuellen Taster den entsprechenden Wert raus geben.
DAS sollte dann aber entweder

  • ein separater Wert für jeden virtuellen Taster sein
  • die gleiche Variable für alle Taster, aber in einer Schleife mit dem entsprechendem Wert geladen, Der dem Taster zugewiesen werden soll.

DANN wirst Du verschiedene Signale für verschiedene Taster zum PC bringen - zumindest theoretisch :wink:

MfG

Hey

Jop das ist kein problem. Wenn ich das so mache dann leuchten auch die button 2 und 4…

Genau da liegt mein problem… wie kriege ich die separaten Werte aus dem schieberegister heraus.?

Wenn ich ja einen taster direkt an einem pin am arduino anschliesse, ist ja über den pin der entsprechende taster definiert und den wert high kann ich dann wenn er anfällt an einen beliebigen virtuellen taster weitergeben.
Dann funktioniert alles und ingame funktionierts auch.

Nur wie mache ich das wenn die werte nacheinander aus dem register raus kommen??

Mfg

Hi

Wie liest Du derzeit das Schieberegister aus?
Ok, ich pack erst Mal Deinen Code hier rein, mom …

/*
 * SN74HC165N_shift_reg
 *
 * Program to shift in the bit values from a SN74HC165N 8-bit
 * parallel-in/serial-out shift register.
 *
 * This sketch demonstrates reading in 16 digital states from a
 * pair of daisy-chained SN74HC165N shift registers while using
 * only 4 digital pins on the Arduino.
 *
 * You can daisy-chain these chips by connecting the serial-out
 * (Q7 pin) on one shift register to the serial-in (Ds pin) of
 * the other.
 * 
 * Of course you can daisy chain as many as you like while still
 * using only 4 Arduino pins (though you would have to process
 * them 4 at a time into separate unsigned long variables).
 * 
*/

/* How many shift register chips are daisy-chained.
*/
#define NUMBER_OF_SHIFT_CHIPS   2

/* Width of data (how many ext lines).
*/
#define DATA_WIDTH   NUMBER_OF_SHIFT_CHIPS * 8

/* Width of pulse to trigger the shift register to read and latch.
*/
#define PULSE_WIDTH_USEC   5

/* Optional delay between shift register reads.
*/
#define POLL_DELAY_MSEC   1

/* You will need to change the "int" to "long" If the
 * NUMBER_OF_SHIFT_CHIPS is higher than 2.
*/
#define BYTES_VAL_T unsigned int

  #include <Joystick.h>

  Joystick_ Joystick;

int ploadPin        = 8;  // Connects to Parallel load pin the 165
int clockEnablePin  = 9;  // Connects to Clock Enable pin the 165
int dataPin         = 11; // Connects to the Q7 pin the 165
int clockPin        = 12; // Connects to the Clock pin the 165

BYTES_VAL_T pinValues;
BYTES_VAL_T oldPinValues;

/* This function is essentially a "shift-in" routine reading the
 * serial Data from the shift register chips and representing
 * the state of those pins in an unsigned integer (or long).
*/
BYTES_VAL_T read_shift_regs()
{
    long bitVal;
    BYTES_VAL_T bytesVal = 0;

    /* Trigger a parallel Load to latch the state of the data lines,
    */
    digitalWrite(clockEnablePin, HIGH);
    digitalWrite(ploadPin, LOW);
    delayMicroseconds(PULSE_WIDTH_USEC);
    digitalWrite(ploadPin, HIGH);
    digitalWrite(clockEnablePin, LOW);

    /* Loop to read each bit value from the serial out line
     * of the SN74HC165N.
    */
    for(int i = 0; i < DATA_WIDTH; i++)
    {
        bitVal = digitalRead(dataPin);

        int bit1 = 0;
        int bit2 = 0;
        int bit3 = 0;

        /* Set the corresponding bit in bytesVal.
        */
        bytesVal |= (bitVal << ((DATA_WIDTH-1) - i));

        /* Pulse the Clock (rising edge shifts the next bit).
        */
        digitalWrite(clockPin, HIGH);
        delayMicroseconds(PULSE_WIDTH_USEC);
        digitalWrite(clockPin, LOW);
    }

    return(bytesVal);
}

/* Dump the list of zones along with their current status.
*/
void display_pin_values()
{
    Serial.print("Pin States:\r\n");

    for(int i = 0; i < DATA_WIDTH; i++)
    {
        Serial.print("  Pin-");
        Serial.print(i);
        Serial.print(": ");

        if((pinValues >> i) & 1)
            Serial.print("HIGH");
        else
            Serial.print("LOW");

        Serial.print("\r\n");
    }

    Serial.print("\r\n");

}

void setup()
{
    Serial.begin(9600);

    Joystick.begin();

    /* Initialize our digital pins...
    */
    pinMode(ploadPin, OUTPUT);
    pinMode(clockEnablePin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, INPUT);

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

    /* Read in and display the pin states at startup.
    */
    pinValues = read_shift_regs();
    display_pin_values();
    oldPinValues = pinValues;
}

void loop()
{
    /* Read the state of all zones.
    */
    pinValues = read_shift_regs();

    /* If there was a chage in state, display which ones changed.
    */
    if(pinValues != oldPinValues)
    {
      
        Joystick.setButton(0,pinValues);
//        Joystick.setButton(1,pinValues);
 //       Joystick.setButton(2,pinValues);
       
        display_pin_values();
        oldPinValues = pinValues;

    }

    delay(POLL_DELAY_MSEC);
}

A-ha … die Variable pinValues wird pro Eingang mit je einem Bit gesetzt.
Deshalb muß man auch

/* You will need to change the "int" to "long" If the
 * NUMBER_OF_SHIFT_CHIPS is higher than 2.
*/
#define BYTES_VAL_T unsigned int

das int (16 bit = Platz für 2 Stück Schieberegister) in LONG ändern, wenn’s Mehr werden sollen.
Soweit, so gut.
Du musst jetzt nur noch die Bits wieder einzeln da raus holen.
Entweder einen Befehl, Der das gewünschte Bit zurück gibt, oder wir teilen stupide immer durch Zwei und nutzen den Rest der Division.
pinValue besteht aus 16 Bit - Du hast 16 Eingänge, Die in PinValue quasi codiert eingetragen sind.

uint16_t todecode=pinValue;
for (byte i=1;i<17;i++){
   joystick.setButton(i,todecode%2==0?LOW:HIGH);
   todecode/=2;
}

Hier wird bei jedem Durchlauf (1 bis 16) geprüft, ob das unterste Bit ungesetzt (==0) ist, wenn JA, wird LOW in den Befehl eingetragen, sonst HIGH.
Das ? ist die Kurzform einer IF-Abfrage (Bedingung ? WAHR-Rückgabe : FALSE-Rückgabe)

MfG

…davon ab, auf Arduino Playground, SN74HC165N ist ein Beispiel-Sketch, Der Dir genau die Einzel-Status der ganzen Taster ausgibt - ziemlich weit oben, der Google-Treffer.
… und schöner gelöst haben 'se Das auch:

        if((pinValues >> i) & 1)
            Serial.print("HIGH");
        else
            Serial.print("LOW");

Hey
Besten dank für deine ausführliche erklährung.
Nun blicke ich schon etwas mehr durch. Jedoch noch nicht ganz...

Hey
Besten dank für deine ausführliche erklährung.
Nun blicke ich schon etwas mehr durch. Jedoch noch nicht ganz
Genau den Sketch habe ich auch verwendet...
Code: [Select]

if((pinValues >> i) & 1)
Serial.print("HIGH");
else
Serial.print("LOW");

Aber der gibt ja die daten seriell an den Monitor aus.
Wie muss ich nun den loop teil schreiben, um diese werte mit dem befehl Joystick.setButton an den PC weiterzugeben?

Könntest du mir evt. ein beispiel machen?
Sorry bin mit den schiftregistern nicht so bewandert...

MFG

Hi

Hier hast Du i als die hochzählende Variable.
Allerdings wird i Null beinhalten, das erste Bit ist eben Bit 0.
Nun musst Du 'nur noch' Deine serielle Ausgabe in die Joystick-Button-Befehle packen.

Deine Joystick-Buttons fangen bei 1 an - die Durchzählung bei 0.
Somit wird wieder
joystick.setButton(i,todecode%2==0?LOW:HIGH);
ins Spiel genommen, etwas an Deinen Snipped angepasst, schauts dann so aus:

joystick.setButton(i+1,(pinValues >> i) & 1==0?LOW:HIGH);

MfG