Go Down

Topic: Determining the Number of Shift Registers Connected to Arduino (Read 537 times) previous topic - next topic

wvmarle

Probably missing something... but how are you going to guarantee that the last shift register, of a variable daisy chain, is linked back? Say you have connectors for up to four shift registers. Normally they daisy chain to one another - so if you have four of them, the fourth sends the data back to the Arduino.

But now if you connect only the first three. Then with the last register missing, the connection to the Arduino is also missing. Or if you connect only the last three, the first is not there, and there's nothing reading the data to begin with so the second to fourth never get any data.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

csapidus

The code previously posted did not use the SPI.Transfer method. I am trying to get an alternative method working without SPI.Transfer, as it complicates the design of my circuit by requiring SPI, when I have an ancillary keypad already using SPI for data transfer.

I will provide the functioning SPI.Transfer code later today, along with posting the Serial outputs

wvmarle

SPI is a bus and can easily be shared between multiple devices. That's what it's designed to do. Just make sure you have a separate CS line for each device.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

Paul__B

However to share, the devices must disable MISO when not selected, which the 74HC595 will not do.

csapidus

However to share, the devices must disable MISO when not selected, which the 74HC595 will not do.

Ah, that will make things quite difficult. The keypad with display ancillary device requires SPI, so I can't get around that. I would be interested in hearing if software SPI would be of use. Does hardware SPI and software SPI share the same effective SPI bus?

Secondly, an interrupt is required for recognizing when a new shift register is added, but I am not sure how best to realize this with attachInterrupt(x, y, z).

Here is the functional code using SPI Transfer:

Code: [Select]

//**************************************************************//
// TESTING SHIFT REGISTER CHAINING
//****************************************************************

// Serial output for various parameters, where SR = number of chained shift registers
// 187, 85, 170 0xAA 1SR

// 187, 255, 204 0xCC 1SR
//  187, 255, 255, 204, 204 0xCC 2SR

#include <SPI.h>
uint16_t SPI_message = 0xCC;

int latchPin = 8;
int blankPin = 9; // connected to OE
int dataPin = 11; // MOSI
int readPin = 12; // MISO
int clockPin = 13; // SCK

int count = 0;

uint16_t SPI_returned = 0xBB;

void setup() {
  Serial.begin(9600);
 
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV2); //Run the data in at 16MHz/2 - 8MHz

  pinMode(latchPin, OUTPUT);
  pinMode(blankPin, OUTPUT);
  // pinMode(readPin, INPUT); // Not necessary
 
  digitalWrite(blankPin, HIGH);
  digitalWrite(latchPin, LOW);

  Serial.print("COUNT: ");
  Serial.println(count);
  Serial.print("READING: ");
  Serial.println(SPI_returned);
}

void loop() { 
  digitalWrite(blankPin, HIGH);
  SPI_returned = SPI.transfer(SPI_message);
  digitalWrite(latchPin, HIGH);
  digitalWrite(latchPin, LOW);
  digitalWrite(blankPin, LOW);

  if (SPI_returned == 255) {
      count++;
  }
     
  Serial.println("COUNT: ");
  Serial.println(count);
  Serial.print("READING: ");
  Serial.println(SPI_returned);
 
  delay(1000);
}

Paul__B

Secondly, an interrupt is required for recognising when a new shift register is added, but I am not sure how best to realise this with attachInterrupt(x, y, z).
That is because you have no idea what an "interrupt" is in a computer or microcontroller.  Sorry about that.

You wish to detect when your modules are "hot-plugged", eh?  The first thing you need to do for this is to arrange the plugs and sockets between each.

If you look carefully, you will see that USB connectors have some pins longer than others, so that when plugging in, the ground connects first, then Vcc, and only then the data pins.  This is how your connectors must be designed and it is not easy.  But once you have solved that, then in order to detect changes in the arrangement, you must periodically test it as described above, by resetting the shift registers and rippling bytes through.

When you get no response at all (the input back to the Arduino must have a 22k pull-down resistor so it defaults to reading zero) you know it has not been connected correctly and simply abort the main routine and repeat the periodic test until it responds correctly.

But note, this has nothing whatsoever to do with interrupts.  It is in fact a part of the main loop which performs the test at an appropriate time in the main loop, before the next cycle of whatever the main loop does.  This is called "polling".

csapidus

That is because you have no idea what an "interrupt" is in a computer or microcontroller.  Sorry about that.

You wish to detect when your modules are "hot-plugged", eh?  The first thing you need to do for this is to arrange the plugs and sockets between each.

If you look carefully, you will see that USB connectors have some pins longer than others, so that when plugging in, the ground connects first, then Vcc, and only then the data pins.  This is how your connectors must be designed and it is not easy.  But once you have solved that, then in order to detect changes in the arrangement, you must periodically test it as described above, by resetting the shift registers and rippling bytes through.

When you get no response at all (the input back to the Arduino must have a 22k pull-down resistor so it defaults to reading zero) you know it has not been connected correctly and simply abort the main routine and repeat the periodic test until it responds correctly.

But note, this has nothing whatsoever to do with interrupts.  It is in fact a part of the main loop which performs the test at an appropriate time in the main loop, before the next cycle of whatever the main loop does.  This is called "polling".
I do appreciate the explanation, and I certainly don't purport to be an expert. I have already managed to get my response function set-up and working. My statement about requiring interrupts was specific to my code and how I would like a sort of continuous or ongoing check rather than periodic checks.

The USB example is an interesting one. I am custom designing all aspects of my PCB, so I have some flexibility in making those details happen.

wvmarle

The ongoing check in your case would be polling at an appropriate interval.
That could be every time loop () runs, that could be every 100 ms - the latter still being "instant" to a human observer - whatever works.
Interrupts are not appropriate here unless you really want to interrupt an ongoing write to the shift registers the moment another one is plugged in.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

Paul__B

Interrupts are not appropriate here unless you really want to interrupt an ongoing write to the shift registers the moment another one is plugged in.
Which you would not know about anyway, because the only way you know when something is plugged in is when you test it.

Which you do by writing to the shift registers.

It is a simple case of a "newbie" not comprehending interrupts, or program design.  :smiley-lol:

csapidus


Go Up