I am trying to repair an old midi controller that won't be recognized. I opened it and there are two boards inside, one with the controller that seems to be broken be broken and the second with the 60 Buttons and 8 of these HCT165M.
My plan is to replace the broken main PCB with an arduino because the manufacturer wants more than 100 dollar for the new motherboard.
I realized that the /CE (Clock enable) Pin of all 165 is soldered to GND but in all examples with arduino and 165 this pin is needed to tell the 165 that it should start sending.
Putting it fix to GND should let the IC send data nonstop, am I right?
How can the arduino know which is the first bit? Any ideas?
Pins from the main PCB to the button/165 PCB: Vcc, Gnd, /PL, CP, Q7. The 165's are cascaded through their serial in/out as usual.
I'm happy for every help that points me into the right direction.
Best regards, Martin
Putting it fix to GND should let the IC send data nonstop, am I right?
Only if the clock to the chip is going continuously, which it might not in your original board.
How can the arduino know which is the first bit? Any ideas?
It can't if the clock is being generated by something else. But if the Arduino is generating the clock then the first bit is at the input after the first clock pulse.
Clock is generated by arduino, and I made some progress with a modified example code I found somewhere in the internet. the sketch supports up to 8 hc165 what perfectly matches my project.
Now i have a different problem: I can only read the first 32 buttons when i set the number of shift chips to 8. Pin32-63 are always low (0-31 are high if not pressed, low when pressed).
When I set it to 4 shift chips, I can read the last 32 buttons (all pins but the ones I pressed are high).
Tested with Duemilanove and Mega2560, here's the code
/*
* 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 4 //8
/* 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 long
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);
/* 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);
/* 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)
{
Serial.print("*Pin value change detected*\r\n");
display_pin_values();
oldPinValues = pinValues;
}
delay(POLL_DELAY_MSEC);
}
I tried some things like let it read all and then the last 32 again but nothing is working...
Thanks in advance and in general to all the helpful people here, you already helped me a lot in the past
got it, simply duplicated some parts of the code so it reads the first 32 and the last 32 in seperate loops, works fine
/*
* 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_CHIPS1 8
#define NUMBER_OF_SHIFT_CHIPS2 4
/* Width of data (how many ext lines).
*/
#define DATA_WIDTH1 NUMBER_OF_SHIFT_CHIPS1 * 8
#define DATA_WIDTH2 NUMBER_OF_SHIFT_CHIPS2 * 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_T1 unsigned long
#define BYTES_VAL_T2 unsigned long
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_T1 pinValues1;
BYTES_VAL_T1 oldPinValues1;
BYTES_VAL_T2 pinValues2;
BYTES_VAL_T2 oldPinValues2;
/* 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_T1 read_shift_regs1()
{
long bitVal1;
BYTES_VAL_T1 bytesVal1 = 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_WIDTH1; i++)
{
bitVal1 = digitalRead(dataPin);
/* Set the corresponding bit in bytesVal.
*/
bytesVal1 |= (bitVal1 << ((DATA_WIDTH1-1) - i));
/* Pulse the Clock (rising edge shifts the next bit).
*/
digitalWrite(clockPin, HIGH);
delayMicroseconds(PULSE_WIDTH_USEC);
digitalWrite(clockPin, LOW);
}
return(bytesVal1);
}
BYTES_VAL_T2 read_shift_regs2()
{
long bitVal2;
BYTES_VAL_T2 bytesVal2 = 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_WIDTH2; i++)
{
bitVal2 = digitalRead(dataPin);
/* Set the corresponding bit in bytesVal.
*/
bytesVal2 |= (bitVal2 << ((DATA_WIDTH2-1) - i));
/* Pulse the Clock (rising edge shifts the next bit).
*/
digitalWrite(clockPin, HIGH);
delayMicroseconds(PULSE_WIDTH_USEC);
digitalWrite(clockPin, LOW);
}
return(bytesVal2);
}
/* Dump the list of zones along with their current status.
*/
void display_pin_values1()
{
Serial.print("Pin States:\r\n");
for(int i = 0; i < (DATA_WIDTH1/2); i++)
{
Serial.print(" Pin1-");
Serial.print(i);
Serial.print(": ");
if((pinValues1 >> i) & 1)
Serial.print("HIGH");
// artnet.write(i, 0)
else
Serial.print("LOW");
// artnet.write(i, 255)
Serial.print("\r\n");
}
Serial.print("\r\n");
}
void display_pin_values2()
{
Serial.print("Pin States:\r\n");
for(int i = 0; i < (DATA_WIDTH2); i++)
{
Serial.print(" Pin2-");
Serial.print(i);
Serial.print(": ");
if((pinValues2 >> i) & 1)
Serial.print("HIGH");
// artnet.write(i, 0)
else
Serial.print("LOW");
// artnet.write(i, 255)
Serial.print("\r\n");
}
Serial.print("\r\n");
}
void setup()
{
Serial.begin(9600);
/* 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.
*/
pinValues1 = read_shift_regs1();
pinValues2 = read_shift_regs2();
display_pin_values1();
display_pin_values2();
oldPinValues1 = pinValues1;
oldPinValues2 = pinValues2;
}
void loop()
{
/* Read the state of all zones.
*/
pinValues1 = read_shift_regs1();
/* If there was a chage in state, display which ones changed.
*/
if(pinValues1 != oldPinValues1)
{
Serial.print("*1Pin value change detected*\r\n");
display_pin_values1();
oldPinValues1 = pinValues1;
}
pinValues2 = read_shift_regs2();
/* If there was a chage in state, display which ones changed.
*/
if(pinValues2 != oldPinValues2)
{
Serial.print("*1Pin value change detected*\r\n");
display_pin_values2();
oldPinValues2 = pinValues2;
}
delay(POLL_DELAY_MSEC);
}
Th int variable type has only 16 bits. The long int has 32 and the long long has 64, so if you use the appropriate variable type for your input / output bit patterns you can do it in one.