/*
* 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 24 digital states from a
* pair of daisy-chained SN74HC165N shift registers and SN74HC595N
* while using only 7 digital pins on the MicroController.
*
* You can daisy-chain these SN74HC165N shift registers 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 7 MicroController pins (though you would have to process
* them 7 at a time into separate unsigned long variables).
*
*/
/* How many shift register chips are daisy-chained.
*/
#define NUMBER_OF_SHIFT_CHIPS 3
/* 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 1000
/* 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
// Define Connections to 74HC165 pins
int ploadPin = 2; // Connects to PL pin 1 Parallel load pin the 165
int clockEnablePin = 12; // Connects to CE pin 15 Clock Enable pin the 165
int dataPin = 13; // Connects to Q7 pin 7 the Q7 pin the 165
int clockPin = 4; // Connects to CP pin 2 the Clock pin the 165
// Define Connections to 74HC595 pins
// ST_CP pin 12
const int latchPin = 17;
// SH_CP pin 11
const int clockPin_595 = 16;
// DS pin 14
const int dataPin_595 = 5;
// Define variables for each pin (initially all LOW)
int r_1 = 0; // Pin-0
int r_2 = 0; // Pin-1
int r_3 = 0; // Pin-2
int r_4 = 0; // Pin-3
int r_5 = 0; // Pin-4
int r_6 = 0; // Pin-5
int r_7 = 0; // Pin-6
int r_8 = 0; // Pin-7
// Function to update the state of the output pins
byte calculateRValue() {
byte r_val = 0;
r_val |= (r_1 << 0); // Pin-0
r_val |= (r_2 << 1); // Pin-1
r_val |= (r_3 << 2); // Pin-2
r_val |= (r_4 << 3); // Pin-3
r_val |= (r_5 << 4); // Pin-4
r_val |= (r_6 << 5); // Pin-5
r_val |= (r_7 << 6); // Pin-6
r_val |= (r_8 << 7); // Pin-7
return r_val;
}
// Function to process incoming serial commands
void processCommand(String command) {
command.trim(); // Trim any trailing or leading whitespace
if (command == "r_1 = 1") r_1 = 1; // Set Pin-0 HIGH
else if (command == "r_1 = 0") r_1 = 0; // Set Pin-0 LOW
else if (command == "r_2 = 1") r_2 = 1; // Set Pin-1 HIGH
else if (command == "r_2 = 0") r_2 = 0; // Set Pin-1 LOW
else if (command == "r_3 = 1") r_3 = 1; // Set Pin-2 HIGH
else if (command == "r_3 = 0") r_3 = 0; // Set Pin-2 LOW
else if (command == "r_4 = 1") r_4 = 1; // Set Pin-3 HIGH
else if (command == "r_4 = 0") r_4 = 0; // Set Pin-3 LOW
else if (command == "r_5 = 1") r_5 = 1; // Set Pin-4 HIGH
else if (command == "r_5 = 0") r_5 = 0; // Set Pin-4 LOW
else if (command == "r_6 = 1") r_6 = 1; // Set Pin-5 HIGH
else if (command == "r_6 = 0") r_6 = 0; // Set Pin-5 LOW
else if (command == "r_7 = 1") r_7 = 1; // Set Pin-6 HIGH
else if (command == "r_7 = 0") r_7 = 0; // Set Pin-6 LOW
else if (command == "r_8 = 1") r_8 = 1; // Set Pin-7 HIGH
else if (command == "r_8 = 0") r_8 = 0; // Set Pin-7 LOW
}
// 74HC595N Pins NUM values
// Define an array to store the state of each output pin
int outputState[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // All pins initially LOW
// Function to update the state of a specific pin
void setOutputState(int pin, int state) {
if (pin >= 0 && pin < 8) {
outputState[pin] = state; // Set the specific pin to HIGH (1) or LOW (0)
}
}
// Function to calculate the total value to send to 74HC595N
//byte calculateRValue() {
// byte r_val = 0;
// for (int i = 0; i < 8; i++) {
// r_val |= (outputState[i] << i); // Shift each pin state to its correct bit position
// }
// return r_val;
//}
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...
*/
// 74HC165 pins
pinMode(ploadPin, OUTPUT);
pinMode(clockEnablePin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, INPUT);
// 74HC595 pins
pinMode(latchPin, OUTPUT);
//pinMode(clockPin_595, OUTPUT);
pinMode(dataPin_595, OUTPUT);
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()
{
// Check if a serial command is available
if (Serial.available() > 0) {
String command = Serial.readStringUntil('\n'); // Read the incoming command
processCommand(command); // Process the command
}
/* Read the state of all zones.
*/
pinValues = read_shift_regs();
// Read Switches
// Get data from 74HC165
// Example: Set the first output HIGH and the second output LOW
//setOutputState(0, 1); // Pin 0 HIGH
//setOutputState(1, 0); // Pin 1 LOW
//setOutputState(2, 1); // Pin 1 LOW
//setOutputState(3, 0); // Pin 1 LOW
//setOutputState(4, 0); // Pin 1 LOW
//setOutputState(5, 0); // Pin 1 LOW
//setOutputState(6, 0); // Pin 1 LOW
//setOutputState(7, 1); // Pin 8 HIGH
// Now calculate the r_val based on the current states of the output pins
byte r_val = calculateRValue();
if(pinValues != oldPinValues)
{
Serial.print("*Pin value change detected*\r\n");
display_pin_values();
oldPinValues = pinValues;
}
// Write to LEDs
// ST_CP LOW to keep LEDs from changing while reading serial data
digitalWrite(latchPin, LOW);
// Shift out the bits
shiftOut(dataPin_595, clockPin, MSBFIRST, r_val);
// ST_CP HIGH change LEDs
digitalWrite(latchPin, HIGH);
delay(500);
delay(POLL_DELAY_MSEC);
}