Selecting from an array.

Hi folks. I’m sure you get a lot of these introductions, but I am yet another new person that is diving into the world of Arduino and it looks like I need a little assistance. I was looking to see if there is a way to select a particular number in an array. I’ve got my code written so that one of 5 LEDs will light up randomly and move on to the next after a specified amount of time. What I’d like to be able to do is when the LED is lit, I want to have to a specific button be pressed in order for that light to go out and move on to the next one. ie when LED2 is activated, Button2 has to pressed in order for the light to be put out. Right now I’ve only got two buttons and two LEDs defined, but here is the code that has been patched together. Thanks in advance for the expertise.

#include <TrueRandom.h>
#include <Button.h>

const int buttonPin1 = 2;
const int buttonPin2 = 3;
const int PIN13 = 13;
const int PIN12 = 12;
const int maxLedPins = 2;
const int maxButtonPins = 2;

boolean buttonState1 = false;
boolean buttonState2 = false;

int buttonPins[maxButtonPins] = {2,3};
int ledPins[maxLedPins] = {12,13};
int buttonPressed1 = 0;
int buttonPressed2 = 0;
int ledState1 = 0;
int ledState2 = 0;

void setup () 
{
  // Set all pins to output
  for (int i=0; i < maxLedPins; i++)
  {
  pinMode(ledPins[i], OUTPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin2, INPUT);
  
    // initialize serial communication:
  Serial.begin(9600);
  }
}

void loop () 
{
  buttonPressed1 = digitalRead(buttonPin1);
  buttonPressed2 = digitalRead(buttonPin2); 

  // Turn off all leds
  for (int i=0; i < maxLedPins; i++) 
 {
   //delay(1000);  //how long between activations
   digitalWrite (ledPins[i], LOW);
 }   
static int loops = 0; // this static variable holds its value between calls to loop()

  if ( loops >= 5)  // how many times to loop
    {
    return; // stops the loop
    } 
  else loops++;  // adds to the loops integer and stops after the specified number
  
  digitalWrite (ledPins[TrueRandom.random(maxLedPins)], HIGH); //using random from maxLedPins variable
     while(digitalRead(buttonPin1) == LOW){}
    
for (int i=0; i < maxLedPins; i++) {
   digitalWrite (ledPins[i], LOW);
  }

delay (500);
}

(code tags added by moderator)

My recommendation is to find yourself a copy of Pragmatic Arduino: A Quick-Start Guide.

What you are doing is essentially one of the very first projects in the book, and it does a very good job explaining whats going on. Your code only ever waits for button one to be pushed, but you want it to wait for the lit LED's button to be pushed. why not store the Rand result in a variable beforehand so you can reuse it later. Regardless, you're going to want to look into Debouncing buttons(it's also covered in the book) because you can get some weird stuff going on signal-wise if you dont.

Cheers

When you define your arrays you don't need to specify the size of your array in the declaration, in your code:

int buttonPins[maxButtonPins] = {2,3};
int ledPins[maxLedPins] = {12,13};

What you've written is ok, however you can also write:

int aryButtonPins[] = {2,3};
int aryLEDPins[] = {12,13};

You can then determine the size of your array using:

const int intMaxButtonPins = sizeof(aryButtonPins) / sizeof(aryButtonPins[0]);
const int intMaxLEDPins = sizeof(aryLEDPins) / sizeof(aryLEDPins[0]);

This means that if you edit your arrays the totals are then calculated for you by the compiler. Notice that I've renamed your variables, this practice just helps anyone reading the code to identify the type of data, in the examples above, arrays are prefixed with 'ary', integers are prefixed with 'int'. You can go a lot further.

I would suggest creating a simple class to wrap up your data into, then you can control access to elements of the data checking for valid indexes and bounds overrun errors in the access methods.

To access any element of the array simply use an index 0 to Number of elements -1. eg.
aryButtonPins[index]

If you want to turn on an specific LED when a specific button is pushed, then attach an interrupt to that button and then you can act accordingly when the button state is HIGH.

I hope this helps.

I did pick up the book just this morning at Barnes and Noble and went through it. I looked at the sections that mentioned the buttons and LEDs, but I didn't really see the correlation. My eventual goal is going to be a mechanical Whack-A-Mole. What I'm trying to get going first is to have a random light turn on and a specific button for that LED. The final setup is going to have one motor and two pressure switches. I want the motor, when activated, to stay running until it hits a switch, then once a length of time has passed or the target gets pushed back, it would then move on to finish up through the loop. Right now I'm looking to have it set up with an LED representing the motor and the button being one of the switches. Well, now that I'm looking at what I'm writing, I'm not quite sure if I am really explaining correctly, but I'll see if I can might be able to reword it slightly. Thanks again for the help.

I think you should use arrays also for button and led states.

Well, I added the buttons to an array and I think I specified it correctly, but for some reason, the two LEDs that I have set up will only turn off when button2 is pressed no matter which LED is lit. When I push button1, it doesn’t do anything. I’m pretty sure that I have my wiring correct, but I still cant quite figure it out. Oddly enough, I have also tried changing the order of the values in the maxButtonPins array and got the same result. Thanks again.

#include <TrueRandom.h>

const int buttonPin1 = 3;
const int buttonPin2 = 2;

const int maxLedPins = 2;
const int maxButtonPins = 2;

boolean buttonState1 = false;
boolean buttonState2 = false;

int buttonPins[maxButtonPins] = {2,3};
int ledPins[maxLedPins] = {12,13};
int buttonPressed1 = 0;
int buttonPressed2 = 0;
int ledState1 = 0;
int ledState2 = 0;


void setup () 
{
  // Set all pins to output
  for (int i=0; i < maxLedPins; i++)
  {
  pinMode(ledPins[i], OUTPUT);
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  
    // initialize serial communication:
  Serial.begin(9600);
  }
}

void loop () 
{
  buttonPressed1 = digitalRead(buttonPin1);  // This isn't the STATE, it is the PRESS
  buttonPressed2 = digitalRead(buttonPin2);

  
  // Turn off all leds
  for (int i=0; i < maxLedPins; i++) 
  
 {
   //delay(1000);  //how long between activations
   digitalWrite (ledPins[i], LOW);
 }   
static int loops = 0; // this static variable holds its value between calls to loop()

  if ( loops >= 5)  // how many times to loop
    {
    return; // stops the loop
    } 
  else loops++;  // adds to the loops integer and stops after the specified number

      digitalWrite (ledPins[TrueRandom.random(maxLedPins)], HIGH); //using random from maxLedPins variable
      if == (ledPins[TrueRandom.random(maxLedPins)]
      
      while(digitalRead(maxButtonPins) == LOW){}

for (int i=0; i < maxLedPins; i++) {
   digitalWrite (ledPins[i], LOW);
  }

delay (500);
}

Edit your comment, select the code and click on the "#" button just above the smiley line.

ty mromani.

In your setup only the statement:

pinMode(ledPins[i], OUTPUT);

Should be in the loop. In your loop() routine, move the delay up to before the for loop that sets the output low....at the moment you are setting the state high, then low without delay.

SPlatten:
When you define your arrays you don't need to specify the size of your array in the declaration, in your code:

What you've written is ok, however you can also write:

int aryButtonPins[] = {2,3};

int aryLEDPins[] = {12,13};




You can then determine the size of your array using:


const int intMaxButtonPins = sizeof(aryButtonPins) / sizeof(aryButtonPins[0]);
const int intMaxLEDPins = sizeof(aryLEDPins) / sizeof(aryLEDPins[0]);




This means that if you edit your arrays the totals are then calculated for you by the compiler. Notice that I've renamed your variables, this practice just helps anyone reading the code to identify the type of data, in the examples above, arrays are prefixed with 'ary', integers are prefixed with 'int'. You can go a lot further.

I would suggest creating a simple class to wrap up your data into, then you can control access to elements of the data checking for valid indexes and bounds overrun errors in the access methods.

To access any element of the array simply use an index 0 to Number of elements -1. eg.
aryButtonPins[index]

If you want to turn on an specific LED when a specific button is pushed, then attach an interrupt to that button and then you can act accordingly when the button state is HIGH.

Sorry I missed your post earlier SPlatten. I'll have to do a little more digging, but are you saying that with the arrays, I could put in "aryButtonPins[2]" and that would call the second value in the array? Thanks again.

are you saying that with the arrays, I could put in "aryButtonPins[2]" and that would call the second value in the array?

No, that would be the third one.

http://arduino.cc/en/Reference/Array

HTH

Ok, I see what you are talking about now. I went ahead and made those changes and pulled out the majority of the other stuff. Kinda bare bones now, but here is the rewrite of the code.

#include <TrueRandom.h>

const int buttonPin1 = 3;
const int buttonPin2 = 2;
const int totalTargets = 2;
const int ledPin1 = 8;
const int ledPin2 = 9;

int aryButtonPins[] = {2,3};
int aryLedPins[totalTargets] = {8,9};

void setup () 
{
}
void loop () 
{   
  for (int i=0; i < TrueRandom.random(totalTargets);)
  {
  // Set the selected pins to output and input
  pinMode(aryLedPins[i], OUTPUT);
  pinMode(aryButtonPins[i], INPUT); 
    {
      static int loops = 0; // this static variable holds its value between calls to loop()
      if ( loops >= 5)  // how many times to loop
        {
         digitalWrite(ledPin1, HIGH);
         digitalWrite(ledPin2, HIGH);
         //return; // stops the loop
        } 
      else loops++;  // adds to the loops integer and stops after the specified number
        for (int i=0; i < TrueRandom.random(totalTargets);) 
        {
      digitalWrite (aryLedPins[i], HIGH); //using random from aryLedPins variable
        while (digitalRead(aryButtonPins[i]) == LOW); {}
      digitalWrite (aryLedPins[i], LOW);
         }
    }
delay (500);
  }
}

Instead of just ending the code I put it so that both LEDs would light up when the code was finished, but I’ve got to double check my wiring in the morning, because it looks like my LED1 decided to crap out on me. I also took out the i++, I’m not sure if that was affecting me or not, I was only getting LED2 light up when it was in the “for (i=0…)” statement. Does this look about right to you guys? Thanks again.

Ok, you have a for loop inside another for loop, nothing wrong with this, but you are using the same variable name in both, again, strictly nothing wrong with it, because you have declared another instance of the variable, but I would strongly recommend against using the same name again, makes reading the code very confusing.

I’m not sure what your while loop is doing inside the second for loop, it looks like you are waiting to see if any LED’s are low, but then you are turning them off again without any delay. You won’t see the transistion from on to off.

I’m not sure if this is what you wanted, try this:

void loop () {   
  static int loops = 0; // this static variable holds its value between calls to loop()

  if ( loops++ >= 5 ) {
    digitalWrite(ledPin1, HIGH);
    digitalWrite(ledPin2, HIGH);
    return;
  }
  for( int i=0; i<TrueRandom.random(totalTargets); i++ ) {
/*  
// Set the selected pins to output and input
    pinMode(aryLedPins[i], OUTPUT);  Move this code into the setup(), no need to do it every iteration 
    pinMode(aryButtonPins[i], INPUT);  
*/
// how many times to loop
    digitalWrite (aryLedPins[i], HIGH); //using random from aryLedPins variable
delay (500);
//    while (digitalRead(aryButtonPins[i]) == LOW); {}
    digitalWrite (aryLedPins[i], LOW);
  }
}

Just a quick reply (I’m in a hurry):

for (int i=0; i < TrueRandom.random(totalTargets);)

You’re missing an i++ here.

for (int i=0; i < TrueRandom.random(totalTargets); i++)

(edit: I was replying to comment #11)

That looks like that did it. Just had to have a second pair of eyes taking a look from a buddy of mine and he was able to make sense where I wasn’t catching it. Thanks sooooooooo much for the help. It is very appreciated.