Go Down

Topic: Maximum number of SN74HC165N (Read 2613 times) previous topic - next topic

Jobi-Wan

Both with LED and with relays, both work correctly.
Then what is your issue at the moment?

If you are using the latest code you posted in reply #20, then you will always set all out outputs LOW. You never set anything to HIGH.

When you change your clearRegisters() function to set everything to HIGH instead of LOW, do all your outputs go high?
How did you test and confirm that your outputs are working?
Can you explain in detail how your program works? Especially writeRegisters() and setRegisterPin()

Herodes

Let's see: I've already managed to reproduce what I did yesterday. Nothing spectacular...

To check that the outputs work, I connect pins 1, 9, 17, 25, ... and change the code manually. I indicate, in this piece of code, the part I change: where it says "setRegisterPin (1, HIGH)" & "setRegisterPin (1, LOW)", I substitute 1 for a 9 and relay 9, goes to LOW.

So the outputs are working with 74HC595. 9 is the value of "i" in the buble "for" when I press the switch connected to pin 9 of the 74HC165. But how do I let Arduino know that there is a 9?

Perhaps building a matrix (array) in the buble "for" that has 0 and 1 (0,1,1,1,0,0,1, ...) and then calling element 9? So I would do it in another programming language but in Arduino I do not know ... I feel strange!


Code: [Select]

...
//74HC595=====================================

  if(estado000 = 1)
  {
    setRegisterPin(9, HIGH);
    estado000 = 0;
  }
  else
  {
    setRegisterPin(9, LOW);
    estado000 = 1;
  }
////////////////////////

  writeRegisters();
  //MUST BE CALLED TO DISPLAY CHANGES
  //Only call once after the values are set how you need.

...


Then what is your issue at the moment?

If you are using the latest code you posted in reply #20, then you will always set all out outputs LOW. You never set anything to HIGH.

The problem is that when I press one of the switches I see a 1 but I do not know how to make that pulsation cause the corresponding relay to move or led to light.

I do not know how to make that pulsation (that input) have an impact on an exit.

With the code of post # 20 Arduino was arranged to read all 74HC165 and, indeed, if you press any switch, regardless of whether it is within the first 8 chips or outside, you get HIGH.

But now I have to be able to reflect that HIGH in an output, be it a relay, an LED ... the outputs work, but so far I have only been able to check it manually.

Jobi-Wan

Ok, cool. In your old code, you had this:
Code: [Select]
  estado000 = digitalRead(pin_Q7);
  ////////////////////////
 
  //Serial.println(boton01);
  if(estado000 == 9) {
    setRegisterPin(9, HIGH);
    //  digitalWrite(13, HIGH);
  }

..which will never happen, because estado000 can be HIGH or LOW but never 9.



The problem is that when I press one of the switches I see a 1 but I do not know how to make that pulsation cause the corresponding relay to move or led to light.
So you have confirmed that you can use setRegisterPin() to set outputs HIGH and low.

When you say "corresponding relay", do you mean input #1 corresponds to relay #1, and #2 to #2, etc..?

In the for-loop, where you print a 1 or a 0, that is where you know the status of one input and you know the number of that input. So instead of just printing a 1 or a 0, you can set the corresponding register pin to HIGH or LOW. (To the same value that the input pin has.)

Even if this is not what you ultimately want, I would still do this first, because it is a good test.

Herodes

..which will never happen, because estado000 can be HIGH or LOW but never 9.
True. I already have a crazy head ...

When you say "corresponding relay", do you mean input #1 corresponds to relay #1, and #2 to #2, etc..?
Not necessarily. Now, to try, but later I want to have the freedom to change that.

In the for-loop, where you print a 1 or a 0, that is where you know the status of one input and you know the number of that input. So instead of just printing a 1 or a 0, you can set the corresponding register pin to HIGH or LOW. (To the same value that the input pin has.)

Even if this is not what you ultimately want, I would still do this first, because it is a good test.

That is exactly where I am now working. Do you think the problem is to use "1" and "0" instead of "HIGH" and "LOW"?

Jobi-Wan

Do you think the problem is to use "1" and "0" instead of "HIGH" and "LOW"?
No.
Inside that for-loop, you read the input, you print the value to a serial port, but you don't do anything to set your outputs.
You have already seen how to set specific output pins, like 1, 9, 17, 25.

If you've made changes that you believe should work, but they don't, then post the latest code again.




Oh and by the way, this doesn't do what you think it does:
Code: [Select]
  if(estado000 = 1)
  {

There is a difference between = and == operators. The 1st one is for assignment, the 2nd if for comparison. Look at other if's where values are being compared. So your condition is always true and you see output 9 go high but never low again.

Herodes

Oh and by the way, this doesn't do what you think it does:
Code: [Select]
  if(estado000 = 1)
  {

There is a difference between = and == operators. The 1st one is for assignment, the 2nd if for comparison. Look at other if's where values are being compared. So your condition is always true and you see output 9 go high but never low again.
Here is the new code.

I have forgotten the variable "estado000".

I have declared two new variables, "index" and "value". "Index" is the entry number that changes. "Value" is 1 or 0. It has not been difficult to find the entry number that goes from 0 to 1. But how to find the entry number that passes in 1 to 0?

Code: [Select]
//____________________________________________
//74HC595=====================================
/* A continuación te pongo cómo tienes que conectar el primer chip
 * al Arduino. Ten en cuenta que los pines se numeran del 1 al 16
 * desde el inferior izquiero (1), en el sentido contrario al movi-
 * miento de las agujas del reloj, viendo la muesca del chip a la
 * izquierda, terminando así en el 16, en la esquina superior iz-
 * quierda, que es Vcc.
 */
  int SER_Pin = 6;   //pin 14 on the 75HC595
  int RCLK_Pin = 7;  //pin 12 on the 75HC595
  int SRCLK_Pin = 8; //pin 11 on the 75HC595

//How many of the shift registers - change this
  #define number_of_74hc595s 20

//do not touch
  #define numOfRegisterPins number_of_74hc595s *8

  boolean registers[numOfRegisterPins];

////////////////////////
//  int estado000 = 1;
////////////////////////

//____________________________________________
//74HC165=====================================
/* A continuación te pongo cómo tienes que conectar el primer chip
 * al Arduino. Ten en cuenta que los pines se numeran del 1 al 16
 * desde el inferior izquiero (1), en el sentido contrario al movi-
 * miento de las agujas del reloj, viendo la muesca del chip a la
 * izquierda, terminando así en el 16, en la esquina superior iz-
 * quierda, que es Vcc.
 * El pin 15 lo he puesto a 9 y rula, así que así queda.
 */
  const uint8_t pin_PL = 10; // to all pins 1
  const uint8_t pin_CP = 11; // to all pins 2
  const uint8_t pin_Q7 = 12; // to pin 9 of the 1ast chip.
//pin 10 of each chip to pin 9 of next chip

  int index;
  int value;

//____________________________________________
//Pantalla20x4·I2C============================
/*Conecta los cables SDA a SDA y SCL a SCL, calamar.*/
  #include <Wire.h>
  #include <LiquidCrystal_I2C.h>
  LiquidCrystal_I2C lcd(0x3f,20,4);
  //Aquí originalmente ponía 0x24. Pues no. Hay que poner 0x3f y rula.


//////////////////////////////////////////////
//////////////////////////////////////////////
void setup(){
 
//____________________________________________
//74HC595=====================================
  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);

  //reset all register pins
  clearRegisters();
  writeRegisters();
 
//____________________________________________
//74HC165=====================================
  Serial.begin(115200);

  pinMode(pin_PL, OUTPUT);
  pinMode(pin_CP, OUTPUT);
  pinMode(pin_Q7, INPUT);

  digitalWrite(pin_PL, HIGH);
  digitalWrite(pin_CP, HIGH);

//____________________________________________
//Pantalla20x4·I2C============================
  //Iniciamos el fondo retroiluminado
  lcd.backlight();
  //lcd.noBacklight();
  //Iniciamos la pantalla
  lcd.init();
  //LCD.
  lcd.setCursor(0,0);
  lcd.print("   Universidad de   ");//Escribir en la LCD
  lcd.setCursor(0,1);
  lcd.print("     Salamanca      ");//Escribir en la LCD
  lcd.setCursor(0,2);
  lcd.print("   EPS de Zamora    ");//Escribir en la LCD
  lcd.setCursor(0,3);
  lcd.print("  Laboratorio TIT   ");//Escribir en la LCD
  //delay(1000);

}

//____________________________________________
//74HC595=====================================
  void clearRegisters()
  {
  //set all register pins to LOW
  for(int i = numOfRegisterPins - 1; i >=  0; i--)
  {
  registers[i] = LOW;
  }
  }

void writeRegisters()
  {
//Set and display registers
//Only call AFTER all values are set how you would like (slow otherwise)
  digitalWrite(RCLK_Pin, LOW);
  //for(int i = numOfRegisterPins - 1; i >=  0; i--){
  for(int i = numOfRegisterPins; i >=  1; i--)
  {
    digitalWrite(SRCLK_Pin, LOW);
    int val = registers[i];
    digitalWrite(SER_Pin, val);
    digitalWrite(SRCLK_Pin, HIGH);
  }
  digitalWrite(RCLK_Pin, HIGH);
  }

void setRegisterPin(int index, int value)
  {
//set an individual pin HIGH or LOW
  ///Serial.println();
  Serial.print(index);
  Serial.print(value);
  Serial.println();
 
  registers[index] = value;
  //writeRegisters();
  }


//////////////////////////////////////////////
//////////////////////////////////////////////
void loop(){
//____________________________________________
//74HC595=====================================

//Serial.println(boton01);
  //if(estado000 = 1)
  //{
  //  setRegisterPin(1, HIGH);
  //  estado000 = 0;
  //}
  //else
  //{
  //  setRegisterPin(1, LOW);
  //  estado000 = 1;
  //}
////////////////////////

  writeRegisters();
  //MUST BE CALLED TO DISPLAY CHANGES
  //Only call once after the values are set how you need.

//____________________________________________
//74HC165=====================================
  // Latch data from input pins into shift registers
  digitalWrite(pin_PL, LOW);
  digitalWrite(pin_PL, HIGH);


/* Aquí tienes también que intervenir. En el bucle tienes que
 * cambiar el parámetro "n" en "i < n". Tienes que poner el
 * número total de pines que quieres que se lean. Este número
 * será igual al número de chips x 8 (esto ya es para logsianos).
 */
  // Read all bits from all shift registers one by one
  for (int i = 0; i < 80; i++)
  {
    if (digitalRead(pin_Q7) == HIGH)
    {
      //Serial.print("1");
      index = i;
      value = HIGH;
      setRegisterPin(index, value);
    }
    else
    {
      //Serial.print("0");
      index = i;
      value = LOW;
      //setRegisterPin(index, value);
    }
     
  // Clock pulse to shift to the next bit
    digitalWrite(pin_CP, LOW);
    digitalWrite(pin_CP, HIGH);
  }
  //Serial.print(digitalRead(pin_Q7));
  ///Serial.println();
  //Serial.print(estado000);
  //Serial.println();
   
//____________________________________________
//Pantalla20x4·I2C============================
//  lcd.clear();//Limpiamos la LCD
//  lcd.print("Primera linea");//Escribimos en la primera linea
//  lcd.setCursor(0,1);//Saltamos a la segunda linea
//  lcd.print("Segunda linea");//Escribimos en la segunda linea
//  lcd.setCursor(0,2);//Saltamos a la tercera linea
//  lcd.print("Tercera linea");//Escribimos en la tercera linea
//  lcd.setCursor(0,3);//Saltamos a la cuarta linea
//  lcd.print("Cuarta linea");//Escribimos en la cuarta linea
 
  //Tiempo de espera para que reinicie el ciclo
  //delay(500);
  }

Jobi-Wan

Code: [Select]
else
{
  //Serial.print("0");
  index = i;
  value = LOW;
  //setRegisterPin(index, value);
}


Why is that setRegisterPin() call commented out?
What was the behavior/issue before you commented it out?


Right now, you can turn outputs high by setting the corresponding input high, but it doesn't go low again when the input goes low. Putting that line back in place should make it go low. Is this not what you were seeing?

Herodes

#37
May 17, 2018, 08:30 pm Last Edit: May 17, 2018, 08:45 pm by Herodes
True true!

I had uncommented "setRegisterPin (index, value)" because I did not see the change to 0. I put delay (500) to see it and yes, it changes to 0.

Well, well ... IT WORKS !!!!

To finish, I had to take into account that the 74SN595 are numbered from 1, while the 74HC165 are numbered from 0. This has forced me to modify the line "registers [index] = value" to "registers [index + 1] = value; " and with this it has already worked as I wanted.

There is not a very fast answer because, of course, it is constantly doing loops, but ... something is something !!!

At least I know how it works !!!

In a next modification, I will use an intermediate matrix between the input and the output that can match an input with another or other outputs. But for today, I'm satisfied!

Again, a thousand thanks!

To correspond minimally with your help, here I leave the code for those who want to use it, and below I leave the graphics of the connections made, so that they do not have to be searched online.

And if someone reads and comes up with some better solution, which surely will be, please, tell us.

Code: [Select]
//____________________________________________
//74HC595=====================================
/* A continuación te pongo cómo tienes que conectar el primer chip
 * al Arduino. Ten en cuenta que los pines se numeran del 1 al 16
 * desde el inferior izquierdo (1), en el sentido contrario al movi-
 * miento de las agujas del reloj, viendo la muesca del chip a la
 * izquierda, terminando así en el 16, en la esquina superior iz-
 * quierda, que es Vcc.
 */
  int SER_Pin = 6;   //pin 14 on the 75HC595
  int RCLK_Pin = 7;  //pin 12 on the 75HC595
  int SRCLK_Pin = 8; //pin 11 on the 75HC595

//How many of the shift registers - change this
  #define number_of_74hc595s 20

//do not touch
  #define numOfRegisterPins number_of_74hc595s *8

  boolean registers[numOfRegisterPins];

//____________________________________________
//74HC165=====================================
/* A continuación te pongo cómo tienes que conectar el primer chip
 * al Arduino. Ten en cuenta que los pines se numeran del 1 al 16
 * desde el inferior izquierdo (1), en el sentido contrario al movi-
 * miento de las agujas del reloj, viendo la muesca del chip a la
 * izquierda, terminando así en el 16, en la esquina superior iz-
 * quierda, que es Vcc.
 * El pin 15 lo he puesto a 9 y rula, así que así queda.
 */
  const uint8_t pin_PL = 10; // to all pins 1
  const uint8_t pin_CP = 11; // to all pins 2
  const uint8_t pin_Q7 = 12; // to pin 9 of the 1ast chip.
//pin 10 of each chip to pin 9 of next chip

  int index;
  int value;

//____________________________________________
//Pantalla20x4·I2C============================
/*Conecta los cables SDA a SDA y SCL a SCL, calamar.*/
  #include <Wire.h>
  #include <LiquidCrystal_I2C.h>
  LiquidCrystal_I2C lcd(0x3f,20,4);
  //Aquí originalmente ponía 0x24. Pues no. Hay que poner 0x3f y rula.


//////////////////////////////////////////////
//////////////////////////////////////////////
void setup(){
 
//____________________________________________
//74HC595=====================================
  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);

  //reset all register pins
  clearRegisters();
  writeRegisters();
 
//____________________________________________
//74HC165=====================================
  Serial.begin(115200);

  pinMode(pin_PL, OUTPUT);
  pinMode(pin_CP, OUTPUT);
  pinMode(pin_Q7, INPUT);

  digitalWrite(pin_PL, HIGH);
  digitalWrite(pin_CP, HIGH);

//____________________________________________
//Pantalla20x4·I2C============================
  //Iniciamos el fondo retroiluminado
  lcd.backlight();
  //lcd.noBacklight();
  //Iniciamos la pantalla
  lcd.init();
  //LCD.
  lcd.setCursor(0,0);
  lcd.print("   Universidad de   ");//Escribir en la LCD
  lcd.setCursor(0,1);
  lcd.print("     Salamanca      ");//Escribir en la LCD
  lcd.setCursor(0,2);
  lcd.print("   EPS de Zamora    ");//Escribir en la LCD
  lcd.setCursor(0,3);
  lcd.print("  Laboratorio TIT   ");//Escribir en la LCD
  //delay(1000);

}

//____________________________________________
//74HC595=====================================
  void clearRegisters()
  {
  //set all register pins to LOW
  for(int i = numOfRegisterPins - 1; i >=  0; i--)
  {
  registers[i] = LOW;
  }
  }

void writeRegisters()
  {
//Set and display registers
//Only call AFTER all values are set how you would like (slow otherwise)
  digitalWrite(RCLK_Pin, LOW);
  for(int i = numOfRegisterPins; i >=  1; i--)
  {
    digitalWrite(SRCLK_Pin, LOW);
    int val = registers[i];
    digitalWrite(SER_Pin, val);
    digitalWrite(SRCLK_Pin, HIGH);
  }
  digitalWrite(RCLK_Pin, HIGH);
  }

void setRegisterPin(int index, int value)
  {
  registers[index+1] = value;
  writeRegisters();
  }


//////////////////////////////////////////////
//////////////////////////////////////////////
void loop(){
//____________________________________________
//74HC595=====================================
  //writeRegisters();
  //MUST BE CALLED TO DISPLAY CHANGES
  //Only call once after the values are set how you need.

//____________________________________________
//74HC165=====================================
  // Latch data from input pins into shift registers
  digitalWrite(pin_PL, LOW);
  digitalWrite(pin_PL, HIGH);


/* Aquí tienes también que intervenir. En el bucle tienes que
 * cambiar el parámetro "n" en "i < n". Tienes que poner el
 * número total de pines que quieres que se lean. Este número
 * será igual al número de chips x 8 (esto ya es para logsianos).
 */
  // Read all bits from all shift registers one by one
  for (int i = 0; i < 80; i++)
  {
    if (digitalRead(pin_Q7) == HIGH)
    {
      //Serial.print("1");
      index = i;
      value = HIGH;
      setRegisterPin(index, value);
    }
    else
    {
     index = i;
      value = LOW;
      setRegisterPin(index, value);
    }
     
  // Clock pulse to shift to the next bit
    digitalWrite(pin_CP, LOW);
    digitalWrite(pin_CP, HIGH);
  }
  //Serial.println();
 
  //Serial.println();
   
//____________________________________________
//Pantalla20x4·I2C============================
//  lcd.clear();//Limpiamos la LCD
//  lcd.print("Primera linea");//Escribimos en la primera linea
//  lcd.setCursor(0,1);//Saltamos a la segunda linea
//  lcd.print("Segunda linea");//Escribimos en la segunda linea
//  lcd.setCursor(0,2);//Saltamos a la tercera linea
//  lcd.print("Tercera linea");//Escribimos en la tercera linea
//  lcd.setCursor(0,3);//Saltamos a la cuarta linea
//  lcd.print("Cuarta linea");//Escribimos en la cuarta linea
 
  //Tiempo de espera para que reinicie el ciclo
  //delay(500);
  }


SN74HC165 (Inputs):


SN74HC595 (Outputs):

Jobi-Wan

Well, well ... IT WORKS !!!!
[...]
At least I know how it works !!!
Congratulations!

To finish, I had to take into account that the 74SN595 are numbered from 1, while the 74HC165 are numbered from 0. This has forced me to modify the line "registers [index] = value" to "registers [index + 1] = value; " and with this it has already worked as I wanted.
You should change your writeRegisters() function so that that 595 are also numbered from zero.
Your registers array is also numbered from zero. With 'index + 1', the last one will be outside the array. For now you won't run into this because you have declared 20 595s (160 registers: 0...159) but you use only 10 (80 registers, 0...79). But when you use all 20 of them, this will be an issue.


Some other advice:

You are now using 1 byte (8 bits) to store the value of each output. You could store 8 outputs in 1 byte: 1 per bit.



Code: [Select]

    if (digitalRead(pin_Q7) == HIGH)
    {
      //Serial.print("1");
      index = i;
      value = HIGH;
      setRegisterPin(index, value);
    }
    else
    {
     index = i;
      value = LOW;
      setRegisterPin(index, value);
    }

This entire block can be simplified into one single line. Basically: you set each register pin to the value you read from the input pin ... but it's not important as this is just a test.


Herodes

Congratulations!
Thanks!
You should change your writeRegisters() function so that that 595 are also numbered from zero.
How?
You are now using 1 byte (8 bits) to store the value of each output. You could store 8 outputs in 1 byte: 1 per bit.
How?
This entire block can be simplified into one single line. Basically: you set each register pin to the value you read from the input pin ... but it's not important as this is just a test.
How?

Jobi-Wan

* For the 'index + 1' / 'numbered from zero' thing:

Code: [Select]
#define number_of_74hc595s 20
#define numOfRegisterPins number_of_74hc595s *8
boolean registers[numOfRegisterPins];


numOfRegisterPins is 160.
Here you have declared registers as 160 booleans.
They are numbered registers[0] ... registers[159].
registers[160] does not exist. (Reading it will give you garbage, writing to it can cause all kinds of weirdness.)

Look closely at your writeRegisters() function. There is a for-loop.



* On storing 8 bits in a byte instead of 1:

I'm not going to walk you through that. Look into 'bitwise operators'.
For now you should not focus on that.



* On turning that block into a single line: (you should not focus on this either, but here goes: )

For example, the 'index' variable.
You assign 'i' to 'index', and then pass 'index' to some function. You might as well pass 'i' directly. This gets rid of 'index' altogether.
In the same way, you assign HIGH or LOW to a variable, and then pass that variable to a function. You might as well pass HIGH or LOW directly and get rid of that variable too.
But we can go further.. The test in the 'if' compares something to HIGH. Something that can only be HIGH or LOW .. ..which is the only difference between the if-block and else-block.
Code: [Select]
if (x == HIGH)
{
  bla(HIGH);
}
else
{
  bla(LOW);
}
is the same as
Code: [Select]
bla(x);


Focus on the 1st point, about the zero based array index and the for-loop in your writeRegisters() function. And then on implementing your own logic for how the outputs respond to the inputs.

Herodes


blender-

Thanks Herodes for building this and Jobi-Wan for the appropriate help and self-help motivation.. reading this helped me understand a lot.

Herodes

Thanks Herodes for building this and Jobi-Wan for the appropriate help and self-help motivation.. reading this helped me understand a lot.
Pleased to have helped you, friend!

Go Up