Guitar Note Detection With Shift Register

I am working on a guitar note detection project with Arduino.

It works by sending output HIGH to the frets one fret at a time and then for each fret that is HIGH, loop through the 6 string inputs and check if it is HIGH.

It works fine as long as only one fret is touching one string. But if an input-string touches two outputs (two guitar frets), it reads LOW always (it is touching two outputs, but actually only one of them is high at a time). Is the voltage somehow being lost when this happens, or what is happening? If I figure that out maybe I can think of a workaround.

Thanks!

duplicate thread

duplicate thread

I expect you'll be hearing from the Global Moderator...

Please don't post Fritzing's . They are not schematics. Please just pick up a black pen and a blank sheet of printer paper, and draw the schematic with labeled pin numbers.
Take a photo of the sheet, and upload it.

Is the voltage somehow being lost when this happens, or what is happening? If I figure that out maybe I can think of a workaround.

Lose the guitar and short the inputs of the chip to each other and see what happens.
There is no 'workaround' for a miswired IC.

If you're setting the frets HIGH one at a time and a string touches two or more frets, you are connecting a HIGH to a LOW. Not a good idea.

The schematic can't be right because the shift register input is serial not parallel. Look at the datasheet.
The only PARALLEL pins are OUTPUTS. Your schematic shows guitar strings as INPUTS.
At the bottom of your Fritzing, where it says 'INPUTS' , there are MULTIPLE INPUTS.
The shift register takes SERIAL IN, NOT PARALLEL. You didn't post your code so I have no idea what
you are doing. Maybe I misunderstood what you are doing but as already pointed out. You can't short
outputs to each other. It doesn't work like that. That's essentially the same as a solder short across
outputs on a PCB.
Post a photo of a real hand drawn schematic on a blank sheet of printer paper or a point to point wiring list
with pin numbers.

If you make the strings Gnd and use pullup resistors on the frets, then measure which fret is low, you can at least tell what the highest grounded fret is. Not sure how differentiate which string grounded a fret, unless the frets are broken up into 6 segments.

Someone gave me a couple of solutions that might work.

  1. Add a diode (Schottky preferred) in each output, with the cathode pointing toward the strings.

  2. Get rid of the shift register and use Arduino outputs then you can switch non high outputs to input.

The first option I have to do some research as to how that works. The second one is pretty clear and I think it should work just fine.

Thanks for your kind replies and sorry, I'll try to upload a proper diagram next time (at the moment I have zero knowledge on how to read or draw one, so I'll need to study first).

(at the moment I have zero knowledge on how to read or draw one, so I'll need to study first).

Electronic Schematic Symbols

raschemmel:
You didn’t post your code

Here it goes. But as per my last comment I will most likely change the approach and rewrite the code accordingly.

int DS_pin = 11;
int STCP_pin = 12;
int SHCP_pin = 13;

boolean registers[8];

int inputString1 = 3;
int inputString2 = 4;
int inputString3 = 5;
int inputString4 = 6;
int inputString5 = 7;
int inputString6 = 8;

int stringValues[6]= {0, 0, 0, 0, 0, 0};


void setup() {

  Serial.begin(115200);

  pinMode(DS_pin, OUTPUT);
  pinMode(STCP_pin, OUTPUT);
  pinMode(SHCP_pin, OUTPUT);

  pinMode(inputString1, INPUT);
  pinMode(inputString2, INPUT);
  pinMode(inputString3, INPUT);
  pinMode(inputString4, INPUT);
  pinMode(inputString5, INPUT);
  pinMode(inputString6, INPUT);

  writereg();
}


//Update the 8 shift register inputs
void writereg() {
  digitalWrite(STCP_pin, LOW);

  for (int i = 7; i >= 0; i--) {
    digitalWrite(SHCP_pin, LOW);
    digitalWrite(DS_pin, registers[i] );
    digitalWrite(SHCP_pin, HIGH);
  }

  digitalWrite(STCP_pin, HIGH);
}


//Update values of strings
int updateStrings(int fretNumber) {

  if (digitalRead(inputString1)) {
    stringValues[0] = fretNumber + 1;
  }

  if (digitalRead(inputString2)) {
    stringValues[1] = fretNumber + 1;
  }

  if (digitalRead(inputString3)) {
    stringValues[2] = fretNumber + 1;
  }

  if (digitalRead(inputString4)) {
    stringValues[3] = fretNumber + 1;
  }

  if (digitalRead(inputString5)) {
    stringValues[4] = fretNumber + 1;
  }

  if (digitalRead(inputString6)) {
    stringValues[5] = fretNumber + 1;
  }
}

void loop() {

  // Reset string values
  stringValues[0] = 0;
  stringValues[1] = 0;
  stringValues[2] = 0;
  stringValues[3] = 0;
  stringValues[4] = 0;
  stringValues[5] = 0;

  // Pass current through each fret, one at a time 
  // and check current for each string
  
  for (int i = 0; i < 8; i++) {
    if (i == 0) {
      registers[7] = LOW;
    } else {
      registers[i - 1] = LOW;
    }
    registers[i] = HIGH;
    writereg();
    updateStrings(i);
  }

    Serial.print("valString1: ");
    Serial.print(stringValues[0]);
    Serial.print(", valString2: ");
    Serial.print(stringValues[1]);
    Serial.print(", valString3: ");
    Serial.print(stringValues[2]);
    Serial.print(", valString4: ");
    Serial.print(stringValues[3]);
    Serial.print(", valString5: ");
    Serial.print(stringValues[4]);
    Serial.print(", valString6: ");
    Serial.println(stringValues[5]);
}

arjuna-deva:
Someone gave me a couple of solutions that might work.

  1. Add a diode (Schottky preferred) in each output, with the cathode pointing toward the strings.

  2. Get rid of the shift register and use Arduino outputs then you can switch non high outputs to input.

Both would work ok. 1) is preferred IMHO, because 2) uses up a lot of Arduino I/O; but 2) is easier to try.

Using the arduino inputs instead of the shifter should work because it's ok to short inputs but not outputs.

You can't do this with a nylon string guitar. Nylon is non-conductive.

The normal key matrix scan would use a 1-of-8 decoder chip like a 74HC138 to set one row at a
time, and read the columns. A shift register is more general, and can emulate a decoder chip,
but the logical choice is a 1-of-N decoder.

Diodes prevent shorting of logic HIGH to LOW, but resistors can also do this, although with
less consistent behaviour on multiple connections being active.

Using resistors will help with robustness - touching an unprotected CMOS chip input may
cause static damage, so in this application you need to add anti-static measures for robust
operation, or you'll be one nylon carpet away from disaster!

Using lowish value resistors on the outputs (say 100 ohms or so) will drain any static as
well as limiting short-circuit currents to safe values (for an ATmega chip at least). The
inputs can have say 4k7 series resistors and built-in pull-ups, but you'll likely need some 10nF
or so capacitors on the inputs to prevent noise spikes being an issue.

I'd suggest routing the outputs to the strings as these are what you touch most often,
and treat frets as inputs - the inputs are more sensitive to stray voltages so this is a
better way that the schematic.