Return terminating loop in shiftin tutorial example

Hello,

I'm building a 5 button controller for a larger project, and I've encountered a bit of a snafu using the tutorial on using shift registers located at https://www.arduino.cc/en/Tutorial/ShftIn11. To the best of my observation it basically cuts off any commands given after the final command of "return myDataIn;"

I've set the circuit up exactly as described in the upper portion of https://www.arduino.cc/en/Tutorial/ShiftIn, using all 8 buttons and the correct resistors, in addition to trying it with only the 5 I need and the rest just pulled down without a button. I have also attempted to comment that line out, which throws an error, and to put that entire section of code in it's very own braces, which also creates an error. In addition I tried removing everything from the declared main loop down, which seemed to allow it to still function somewhat, but it produced random results

I understand that the return function can be used to go back to the beginning early, and I think that's what's happening here. I understand that I can overcome this issue by simply placing this bit of code at the very end of the larger project, but the why is bothering me. Why write a program to read buttons the build it so that you can do nothing with those buttons afterward? Also is there a way to contain this return so I don't have to move this to the end of my program.

I'm including a slight modification of the tutorial code which will display the problem on the serial monitor. Look for the last line that says this line does not work.

//**************************************************************//
//  Name    : shiftIn Example 1.1                              //
//  Author  : Carlyn Maw                                        //
//  Date    : 25 Jan, 2007                                      //
//  Version : 1.0                                               //
//  Notes   : Code for using a CD4021B Shift Register       //
//          :                                                   //
//****************************************************************

//define where your pins are
int latchPin = 8;
int dataPin = 9;
int clockPin = 7;

//Define variables to hold the data
//for shift register.
//starting with a non-zero numbers can help
//troubleshoot
byte switchVar1 = 72;  //01001000

void setup() {
  //start serial
  Serial.begin(9600);

  //define pin modes
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, INPUT);

}

void loop() {

  //Pulse the latch pin:
  //set it to 1 to collect parallel data
  digitalWrite(latchPin,1);
  //set it to 1 to collect parallel data, wait
  delayMicroseconds(20);
  //set it to 0 to transmit data serially  
  digitalWrite(latchPin,0);

  //while the shift register is in serial mode
  //collect each shift register into a byte
  //the register attached to the chip comes in first
  switchVar1 = shiftIn(dataPin, clockPin);

  //Print out the results.
  //leading 0's at the top of the byte
  //(7, 6, 5, etc) will be dropped before
  //the first pin that has a high input
  //reading  
  Serial.println(switchVar1, BIN);

//white space
Serial.println("-------------------");
//delay so all these print satements can keep up.
delay(500);

}

//------------------------------------------------end main loop

////// ----------------------------------------shiftIn function
///// just needs the location of the data pin and the clock pin
///// it returns a byte with each bit in the byte corresponding
///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0

byte shiftIn(int myDataPin, int myClockPin) {
  int i;
  int temp = 0;
  int pinState;
  byte myDataIn = 0;

  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, INPUT);
//we will be holding the clock pin high 8 times (0,..,7) at the
//end of each time through the for loop

//at the begining of each loop when we set the clock low, it will
//be doing the necessary low to high drop to cause the shift
//register's DataPin to change state based on the value
//of the next bit in its serial information flow.
//The register transmits the information about the pins from pin 7 to pin 0
//so that is why our function counts down
  for (i=7; i>=0; i--)
  {
    digitalWrite(myClockPin, 0);
    delayMicroseconds(0.2);
    temp = digitalRead(myDataPin);
    if (temp) {
      pinState = 1;
      //set the bit to 0 no matter what
      myDataIn = myDataIn | (1 << i);
    }
    else {
      //turn it off -- only necessary for debuging
     //print statement since myDataIn starts as 0
      pinState = 0;
    }

    //Debuging print statements
    //Serial.print(pinState);
    //Serial.print("     ");
    //Serial.println (dataIn, BIN);

    digitalWrite(myClockPin, 1);

  }
  //debuging print statements whitespace
  //Serial.println();
  //Serial.println(myDataIn, BIN);
  return myDataIn;
  Serial.println ("this line does not work");
}

You need to go on a C programming course! Yes, "return" ends a function immediately, no point putting code lines after it. Why do you feel the need to do that? Whatever your reason is, it is due to a misunderstanding on you part. We can help you understand.

Why are you not using the standard built-in shiftIn() Arduino function? You may have been using it by accident when you commented out your own shiftIn() function.

PaulRB:
You need to go on a C programming course! Yes, "return" ends a function immediately, no point putting code lines after it. Why do you feel the need to do that? Whatever your reason is, it is due to a misunderstanding on you part. We can help you understand.

Why are you not using the standard built-in shiftIn() Arduino function? You may have been using it by accident when you commented out your own shiftIn() function.

Paul,

Thank you for your response.

As to why I'm not using the standard built-in shiftin () function, I didn't realize that there was a different method. I quite literally pulled this all off of the arduino.cc tutorial for shifting in. This was the simplest piece of code that Ms. Maw (the name in the credits) wrote. The only line of what I wrote was the bit at the end that said "this line doesn't work". If there is a simpler way I'd love to see it as a tutorial.

As to my C programming course, I'm learning as fast as I can, around a heavy school load. I'm trying hard to not only copy and paste code from tutorials, but to learn how it actually works as I go, and write my own as much as I can. This is the first piece I've not been able to manipulate, beyond pulling the inputs out of the code as copied directly and using them.

-Eric

Perhaps that is a rather old tutorial.

For the built-in function, go to the top of this web page and click Learning --> Reference. The shiftIn() function is under Advanced I/O in the right hand column. To use it, you must delete the whole definition of shiftIn() from your sketch, because that is overriding the built-in function. When you use the built-in function, you must add a third parameter of either LSB_FIRST or MSB_FIRST. Try both and see what happens.

Again Paul, thank you for your patience and replies.

I went to the reference as directed, pulled the newer version of code, and tried writing a very simple shiftin program. It took a bit of tinkering with but I got it to upload, and run, but now I'm getting either a 255 or 0, no in between, regardless of if I press a button or not. I still have everything connected exactly as in the tutorial, and I'm using a cd4021B shift register just like the tutorial. I did, at one time try pulling the pulldown resistors to see if maybe that was affecting it, with no change. As a note I did some more searching and found some stuff about this specific register possibly not functioning 100% with the shiftin function, but that was also people using the spi library to shiftin, if I'm not mistaken, so I may be incorrect. I'll post my code below. With notations. So in your opinion, did I miswrite code, have it wired wrong, or am I now using an incompatible shift register?

int latchPin = 9;
int dataPin = 8;
int clockPin = 7;
void setup (){
Serial.begin(9600);
/*byte incoming = B10010;
 * done to see if there was any change by starting with a defined 
 * byte. Nothing changed. 
 */
}
void loop (){
/*digitalWrite(latchPin,LOW);//done to see if it was reading on
the rising edge per the reference doc. setting the latchpin low causes it to print a 20
or so 0's  then 20 or so 255's. 
*/
byte incoming = shiftIn(dataPin, clockPin, LSBFIRST);
/* I did both LSB and MSB. Doesn't seem to make any difference. 
 */
Serial.println (incoming);
delay(500);
Serial.println (".........");
}

PaulRB:
Perhaps that is a rather old tutorial.

For the built-in function, go to the top of this web page and click Learning --> Reference. The shiftIn() function is under Advanced I/O in the right hand column. To use it, you must delete the whole definition of shiftIn() from your sketch, because that is overriding the built-in function. When you use the built-in function, you must add a third parameter of either LSB_FIRST or MSB_FIRST. Try both and see what happens.

You need to make the latch line briefly high and then low again before you shift in the data.

I made it go high-low Still misbehaving. Once my big roll of resistors makes it's way in from china, if you want I'll send you a register, resistors and buttons set so you can mess about with it all in person. For now I have working code, even if I have to put it at the end so the return doesn't interfere with anything else. One final question, what part number shiftin register do you use? I don't mind ordering another set, they are reasonably cheap, I'd just like to know that they work using the intended code.

Post your working code and a schematic. This should not be difficult to get working.

I don't have any 4021 chips, but i do use pcf8574, which can be used for the same purpose.

Pcf8574 is an i2c I/o expander chip, so you can use it for extra inputs or outputs. For example I have used one to scan a 4x4 keypad. To do that, you use 4 of the pins as outputs and the other 4 as inputs.

Sorry it took so long to respond. I've been really busy IRL. Thank you for offering to look at the code, I really appreciate it.

So I knew that I couldn't be the only person having difficulties, I went out there and dug to find someone else who had used one of these specific shift registers without using the outdated tutorial to do it. Long story short I found something close enough I could figure out what was wrong with mine. I'm attaching the code that I kludged together. It's as simple of an example of a working CD4021 shift register as I can manage. No music notes, or random countdown functions, and definitely no returns. It retrieves data in a straightforward manner, and reports it without any manipulation. It's written for an UNO. I'm sure you could probably figure this out on your own, but it may save some other noob the same headache I faced.

//Define pins
int dataPin = 9;   // Pin 9  connected to Pin 3 of CD4021
int clockPin = 7;  // Pin 7  connected to Pin 10 of CD4021
int latchPin = 8;  // Pin 8  connected to Pin 9 of CD4021

//Define variable
byte Registervalue = 0;  // Used to hold data from DC4021

void setup() {

//define pin modes and start the serial monitor at 9600 baud
  pinMode(dataPin, INPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT); 
  Serial.begin(9600);

}

void loop() {

  //Set latch pin to 1 to get recent data into the CD4021
digitalWrite(latchPin,1);
  
delayMicroseconds(20);
  
  //Set latch pin to 0 to get data from the CD4021
digitalWrite(latchPin,0);

  //Get CD4021 register data in byte variable
Registervalue = shiftIn(dataPin, clockPin, MSBFIRST);


Serial.println(Registervalue);
delay(500);

}

I said:

PaulRB:
You need to make the latch line briefly high and then low again before you shift in the data.

And you said:

Eric_Barnes:
I made it go high-low Still misbehaving.

But you did not post that code so we could not check it for you.
Your new code does exactly that.

You have wasted my time and your own. I hope you eventually learn how to cooperate with someone when you ask for their help.

Wow. I must say that I'm impressed. I've never met that kind of response in thanking someone for their help, nor did I expect it in this situation.

No, I didn't post the broken code that I started with. I found an example of working code for another system, figured out what I was doing wrong, and fixed my own broken code from there. I thanked you for the help you offered, then in the spirit of community, shared the working solution so that others might benefit from it. I won't make that mistake again. I apologize for the gross waste of time. I'll not darken your doorstep, figuratively, again.