Repeating a function

Hello folks, very new to arduino and programming, and first time posting. I teach chemistry and physics at a small(ish) school, and had the opportunity to bring robotics and arduino to my students. I have a pretty good grasp on the electronics, but I am learning programming at the same pace (sometimes slower) than my students. You'll probably see me on here a lot XD

We are learning to use the serial monitor to provide inputs. Below is a code that is supposed to run an 8-LED array in a sequence or pattern. In theory, when the user types '1' into the serial monitor, it should start the sequence and repeat until the user types 'x'. I have tried several things (while loops, serial.peek, !=, etc), but we always have one of two problems: either the '1' input only provides on step in the sequence (to get the pattern to run, you have to enter 1 over and over) or it gets caught in the pattern loop forever and x won't clear it. Below is the code that goes through the LEDs in "steps"

/*

*/

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;

int power = 12; //sets power to run through Pin 12

byte patterns[30] = {
B00000011, 50,
B00000110, 50,
B00001100, 50,
B00011000, 50,
B00110000, 50,
B01100000, 50,
B11000001, 50,
B10000010, 50,
B00000100, 50,
B00001000, 50,
B00010000, 50,
B00100000, 50,
B01000000, 50,
B10000000, 50
};
int index = 0;
int count = sizeof(patterns) / 2;

void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
  pinMode(power, OUTPUT); //makes sure pin 12 provides power
  Serial.begin(9600);
  while (! Serial); // Wait untilSerial is ready - Leonardo
  Serial.println("Enter 1 to start or 'x' to clear");
}

void loop() 
{
  if (Serial.available())
  {
    char ch = Serial.read();
    if (ch == '1')
    {
    digitalWrite(power,HIGH);
      updateShiftRegister();
    }
    if (ch == 'x')
    {
      digitalWrite(power,LOW); //when "cleared" power to pin 12 is turned to ground
      Serial.println("Cleared");
    }
  }
}

void updateShiftRegister()

{
  digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, patterns[index * 2]);
digitalWrite(latchPin, HIGH);
delay(patterns[(index * 2) + 1]);
index++;
if (index >= count){
index = 0;
}
}

Thanks for the help and advice!

either the '1' input only provides on step in the sequence (to get the pattern to run, you have to enter 1 over and over)

Because that is the way you have coded it.

or it gets caught in the pattern loop forever and x won't clear it.

You haven't posted code that illustrates this.

It seems to me that you want to separate reading serial data from taking action on that serial data. If there is something to read, read it.

Then, take some action based on the last thing read.

That way, when you send a '1', the program will see that there is something to read, and read it. Then, the program will see that the last thing read was a '1', so it will do the '1' thing once.

Then, loop() gets called again. There is nothing new to read, so the '1' action gets performed again. This will keep happening until there IS something new to read.

Here is an example of a code that repeats. The only difference is the serial.peek instead of read.

void loop() 
{
  if (Serial.available())
  {
    char ch = Serial.peek();
    if (ch == '1')
    {
    digitalWrite(power,HIGH);
      updateShiftRegister();
    }
    if (ch == 'x')
    {
      digitalWrite(power,LOW); //when "cleared" power to pin 12 is turned to ground
      Serial.println("Cleared");
    }

How would I write a program that continuously monitors for serial changes? I understand the "logic" of what needs to happen, and I know why this code is doing what it's doing. What I don't know is the arduino language and how to write the proper code.

How would I write a program that continuously monitors for serial changes?

char ch;

void loop()
{
   if(Serial.available() > 0)
   {
       ch = Serial.read();
   }

   // Use the value in ch...
}
int latchPin = 5;
int clockPin = 6;
int dataPin = 4;

int power = 12; //sets power to run through Pin 12

byte patterns[30] = {
B00000011, 50,
B00000110, 50,
B00001100, 50,
B00011000, 50,
B00110000, 50,
B01100000, 50,
B11000001, 50,
B10000010, 50,
B00000100, 50,
B00001000, 50,
B00010000, 50,
B00100000, 50,
B01000000, 50,
B10000000, 50
};
int index = 0;
int count = sizeof(patterns) / 2;

void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
  pinMode(power, OUTPUT); //makes sure pin 12 provides power
  Serial.begin(9600);
  while (! Serial); // Wait untilSerial is ready - Leonardo
  Serial.println("Enter 1 to start or 'x' to clear");
}

void loop() 
{
  if (Serial.available())
  {
    char ch = Serial.read();
    if (ch == '1')
    while (ch == '1') // new
    {
      digitalWrite(power,HIGH);
      updateShiftRegister();
      if (Serial.available()) ch=Serial.read(); //new
    }
    if (ch == 'x')
    {
      digitalWrite(power,LOW); //when "cleared" power to pin 12 is turned to ground
      Serial.println("Cleared");
    }
  }
}

void updateShiftRegister()

{
  digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, patterns[index * 2]);
digitalWrite(latchPin, HIGH);
delay(patterns[(index * 2) + 1]);
index++;
if (index >= count){
index = 0;
}
}

Awesome! That does the trick.
I see know, at the end of the shiftregister() I need to supply the command to read the serial again. Makes sense.

why, though, the "while ch == 1" and "if ch == 1"? I tried it with just the while statement, and it still works?
Just trying to take in as much knowledge as I can!

Your correct.. The if-statemant can be safely removed!
Theese constants:

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;

use 6 bytes of memory

#define latchPin  5
#define  clockPin  6
#define  dataPin  4

does not.

Ok, can you explain that to me? What is the difference?
When should I use #define, and when int?

knut_ny:
Theese constants:

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;

use 6 bytes of memory

#define latchPin  5

#define  clockPin  6
#define  dataPin  4



does not.

You must be old school like I am. I believe it's considered better form these days to do:

const int latchPin = 5;
const int clockPin = 6;
const int dataPin = 4;

I believe the compiler can still save the same amount of memory as the #defines but this way you get type checking (maybe I should use 'const byte' instead?)

Just a thought.

Regards,

Brad
KF7FER

believe it's considered better form these days to do:

No, it is considered better form to express pin numbers as "const byte"

leejones15:
Ok, can you explain that to me? What is the difference?
When should I use #define, and when int?

To answer your question:

If you use a data type, such as an int (or byte), you are declaring a variable that can be changed (and may have an initial value). As such, it takes up memory.

You use a #define (or the 'const' keyword) for a 'magic number' or a number that won't ever change. The compiler will insert the value instead of reserving space for a variable, thus saving memory at run-time.

That's the difference in a nutshell anyways.

And thanks to AWOL for the correction - I was thinking it should be byte but wasn't 100% sure (hence the disclaimer).

I hope this helps,

Brad
KF7FER