Making paterns/sequences(noob question, I bet)

(I hope I placed this right, in doubt between programming and this forum)

OK, so I'm getting along nicely with my Arduino Uno now, so I decided to stop fooling around with making 2 or 3 LED's blink, and plug that 595 chip in that I got with my pack. The tutorial was easy enough, just make sure you wire it up correctly, load the code, rock 'n roll.

But that's no fun! I want to do some stuff myself. So I got to playing around, but the only way I can get it to work, is by writing out the complete code, no easy tricks to make it do what I want it to do. So here it is: I want to make 8 LED's blink around in a certain pattern, for example: LED1 on, delay, LED1 off LED2 on, delay, etc. Now I can do this by writing out the individual pieces of the pattern easily enough. What I want to do is make it do it by itself, if at all possible. I've found some code examples but they do not do what I want, and I couldn't figure out how to adapt them(the "one by one" example from the tutorial section on this site, for instance, is one fixed sequence which does not make the LED's go blinky the way I want them to blinky).

Code example of what I have now (not the complete thing, that one is terribly long)

digitalWrite(latch, LOW);
  shiftOut(data, clock, MSBFIRST, B00000001);
  digitalWrite(latch, HIGH);
  delay(time);
  digitalWrite(latch, LOW);
  shiftOut(data, clock, MSBFIRST, B10000000);
  digitalWrite(latch, HIGH);
  delay(time);
  digitalWrite(latch, LOW);
  shiftOut(data, clock, MSBFIRST, B00000010);
  digitalWrite(latch, HIGH);
  delay(time);
  digitalWrite(latch, LOW);
  shiftOut(data, clock, MSBFIRST, B01000000);
  digitalWrite(latch, HIGH);
  delay(time);
  digitalWrite(latch, LOW);
  shiftOut(data, clock, MSBFIRST, B00000100);
  digitalWrite(latch, HIGH);
  delay(time);
  digitalWrite(latch, LOW);
  shiftOut(data, clock, MSBFIRST, B00100000);
  digitalWrite(latch, HIGH);
  delay(time);
  digitalWrite(latch, LOW);
  shiftOut(data, clock, MSBFIRST, B00001000);
  digitalWrite(latch, HIGH);
  delay(time);
  digitalWrite(latch, LOW);
  shiftOut(data, clock, MSBFIRST, B00010000);
  digitalWrite(latch, HIGH);
  delay(time);
  digitalWrite(latch, LOW);
  shiftOut(data, clock, MSBFIRST, B00001000);
  digitalWrite(latch, HIGH);
  delay(time);

and so on...

So questions: 1: Is there a shorter way of how to make it blink such a pattern? 2: If there is, how? 3: Is it possible to get 2 or more LED's on at the same time, using the method requested in question 2?

Thanks in advance. (If this question has been asked for thousands of times, I am terribly sorry but I could not find a way to use the register and make it do my thing).

Everyone was a newbie once, no shame in that. Noobs on the other hand never learn, they just keep asking the same question. I hope your are a newbie, not a noob :wink:

Well, the first thing you have to understand is that you have a simple byte variable, and the shiftOut() just echoes this variables content’s on you 595 outputs. In your code example you have used a constant, like B00000010, instead of a variable. In other words you could have written

byte Pattern ; // outside any other function
  :
Pattern = B00000100 ;
digitalWrite(latch, LOW);
shiftOut(data, clock, MSBFIRST, Pattern);
digitalWrite(latch, HIGH);

The next thing to focus on is that B00000100 = 4 = 0x4, ie it does not matter what number system you use (binary, decimal, hexadecimal) it is the underlying pattern that shows up. Or, if you say Pattern = 77 ; (and then the shiftOut-stuff) then you see what 77(decimal) is in binary on the LEDs.

So, you now can use simply counting

//inside the loop(), instead of your code
  digitalWrite(latch, LOW);
shiftOut(data, clock, MSBFIRST, Pattern++);
digitalWrite(latch, HIGH);
delay(100);

To get your running sequence, you use the fact that a number multiplied by 2 is the same as shifting all bits one step left. Or indeed use the shift function. You have to initialize Pattern to 1 in the setup() ; then replace the Pattern++ with Pattern<<1. Unfortunatly this ony runs through once, so we need to reset it 1 after it the last it is pushed out the left edge, so we add at the bottom if (Pattern==0) Pattern = 1 ;

To go the other way use Pattern>>1 and (re)intitalize to B10000000.

To go to and fro … I’ll leave you to do the details, but it involves another variable Dir which is 1 or 2 to say if your going left or right, and then use the if (Dir==1) Pattern<<1 and the same the other way, and then to detect when to change the Dir value (when == to B10000000 or == B00000001)

Well that explains a big chunk of what I need to do. I'll get to it tomorrow evening and then see if I have understood what you have written here.

And to make it clear, I'm definitely a newbie if you go at it like that, not a noob ;) Once someone has told me something and I understand what has been told, I store it somewhere so I can always fall back, but mostly I remember since I don't stop working on it until I am sure I have a firm grip on the logic ;)

Thanks!

OK so I tried to use the codes that you proposed but this does exactly the same thing as the tutorial codes I found do, namely, push the bits out 1 at a time until all are lit, and then start over again.

What I am looking for is a way to jump the LED's on one at a time, first bit 1, then bit 8, then 2, then 7, etc. Further on there is more code, but that's for later.

The code you propose does: Light bit 1, then 2, then 1,2,3, then 1,2,3,4, and so on.

As if the lights are pushing each other through the sequence.

Nope. Something else is wrong. Or you have misunderstood my point(s). I see now on reading your code and other stuff closer that you are looking for a particular pattern. I tried to explain that using variables and loops you can generate the pattern rather than coding it as one long sequence.

The question is if we can find an expression that makes the values appear. If this gets too complicated, then we can make a list of the patterns. Lets try the list first.

// define a list with the 8 patterns
byte P1[] = { B00000001, B10000000, B00000010, B01000000, B00000100, B00100000, B00001000, B00010000 } ;

void loop () {
for ( int i = 0 ; i < 8 ; i++ ) {
  digitalWrite(latch, LOW);
  shiftOut(data, clock, MSBFIRST, P1[i]);
  digitalWrite(latch, HIGH);
  delay(200) ;
  }
for ( int i = 5 ; i >= 0 ; i-- ) { // go backwards thorugh list, except last 2
  digitalWrite(latch, LOW);
  shiftOut(data, clock, MSBFIRST, P1[i]);
  digitalWrite(latch, HIGH);
  delay(200) ;
  }
// this is my first use of "for" in the code I show you. You get one pattern run for each loop() execution.

For the pattern we’ve got to think of something that makes the numbers 0, 255, 1, 254, … and I think that is too hard. If I focus on the bit pattern it is both f the “<< 1” stuff I described earlier.

We just alternate between the one that that goes left and right

byte R, L ;

void loop () {
if (R==0) R = B10000000;
if (L==0) R = B00000001;
digitalWrite(latch, LOW);
shiftOut(data, clock, MSBFIRST, R);
digitalWrite(latch, HIGH);
delay(200) ;
digitalWrite(latch, LOW);
shiftOut(data, clock, MSBFIRST, L);
digitalWrite(latch, HIGH);
delay(200) ;
// here we make one step in the pattern for each loop() execution
}

I hope you now have
(a) the code you need (two variations even!)
(b) enough starting points to go do other exciting patterns!

Ok, that is what I was looking for. Why did I not think of using it in an array? Thanks a bunch!

Now I can indeed start working on other patterns, since using the array makes it all way more easy.

I started this thread since I want to start something more than using 8 LED's, and start playing with multiple shift registers and such. I got the schematic figured out, but I rather try it all small before I go using more hardware and get even more confused ;) Thanks again!

Code examples not tested... so post a feedback if/when you find improvements 8)

I tested them and they work,I adapted the second part though, because it skipped a piece. I changed

for ( int i = 5 ; i >= 0 ; i-- ) { // go backwards thorugh list, except last 2

to

for ( int i = 6 ; i >= 0 ; i-- ) { // go backwards thorugh list, except last 2

The rest works exactly like I planned it to.

I added some more patterns too, don't have them at hand but I will post them later.